1 21 22 package org.apache.derby.impl.sql.compile; 23 24 import org.apache.derby.iapi.services.context.ContextManager; 25 26 import org.apache.derby.iapi.error.StandardException; 27 28 import org.apache.derby.iapi.sql.compile.CompilerContext; 29 import org.apache.derby.iapi.sql.compile.CostEstimate; 30 import org.apache.derby.iapi.sql.compile.Visitable; 31 import org.apache.derby.iapi.sql.compile.Visitor; 32 import org.apache.derby.iapi.sql.compile.C_NodeTypes; 33 34 import org.apache.derby.iapi.sql.dictionary.DataDictionary; 35 import org.apache.derby.iapi.reference.SQLState; 36 import org.apache.derby.iapi.reference.ClassName; 37 38 import org.apache.derby.iapi.types.DataTypeDescriptor; 39 40 import org.apache.derby.iapi.sql.execute.ExecRow; 41 42 import org.apache.derby.iapi.sql.Activation; 43 import org.apache.derby.iapi.types.DataValueDescriptor; 44 import org.apache.derby.iapi.sql.Row; 45 import org.apache.derby.iapi.types.DataTypeDescriptor; 46 import org.apache.derby.iapi.sql.ResultSet; 47 import org.apache.derby.iapi.types.TypeId; 48 49 import org.apache.derby.iapi.services.loader.GeneratedMethod; 50 51 import org.apache.derby.iapi.services.compiler.MethodBuilder; 52 import org.apache.derby.iapi.services.compiler.LocalField; 53 54 55 import org.apache.derby.iapi.services.sanity.SanityManager; 56 57 import org.apache.derby.iapi.store.access.Qualifier; 58 59 import java.lang.reflect.Modifier ; 60 61 import org.apache.derby.impl.sql.compile.ExpressionClassBuilder; 62 import org.apache.derby.impl.sql.compile.ActivationClassBuilder; 63 import org.apache.derby.impl.sql.execute.OnceResultSet; 64 65 import org.apache.derby.iapi.util.JBitSet; 66 import org.apache.derby.iapi.util.ReuseFactory; 67 import org.apache.derby.iapi.services.classfile.VMOpcode; 68 69 import java.util.Properties ; 70 import java.util.Vector ; 71 72 102 103 public class SubqueryNode extends ValueNode 104 { 105 114 ResultSetNode resultSet; 115 116 117 int subqueryType; 118 119 122 boolean underTopAndNode; 123 124 125 boolean preprocessed; 126 127 128 boolean distinctExpression; 129 130 137 ValueNode leftOperand; 138 boolean pushedNewPredicate; 139 140 145 BinaryComparisonOperatorNode parentComparisonOperator; 146 147 151 private BooleanConstantNode trueNode; 152 153 155 156 private int subqueryNumber = -1; 157 158 159 private int pointOfAttachment = -1; 160 161 165 private boolean foundCorrelation; 166 private boolean doneCorrelationCheck; 167 168 173 private boolean foundVariant; 174 private boolean doneInvariantCheck; 175 176 184 public final static int NOTIMPLEMENTED_SUBQUERY = -1; 185 public final static int FROM_SUBQUERY = 0; 186 public final static int IN_SUBQUERY = 1; 187 public final static int NOT_IN_SUBQUERY = 2; 188 public final static int EQ_ANY_SUBQUERY = 3; 189 public final static int EQ_ALL_SUBQUERY = 4; 190 public final static int NE_ANY_SUBQUERY = 5; 191 public final static int NE_ALL_SUBQUERY = 6; 192 public final static int GT_ANY_SUBQUERY = 7; 193 public final static int GT_ALL_SUBQUERY = 8; 194 public final static int GE_ANY_SUBQUERY = 9; 195 public final static int GE_ALL_SUBQUERY = 10; 196 public final static int LT_ANY_SUBQUERY = 11; 197 public final static int LT_ALL_SUBQUERY = 12; 198 public final static int LE_ANY_SUBQUERY = 13; 199 public final static int LE_ALL_SUBQUERY = 14; 200 public final static int EXISTS_SUBQUERY = 15; 201 public final static int NOT_EXISTS_SUBQUERY = 16; 202 public final static int EXPRESSION_SUBQUERY = 17; 203 204 205 212 213 public void init( 214 Object resultSet, 215 Object subqueryType, 216 Object leftOperand) 217 { 218 this.resultSet = (ResultSetNode) resultSet; 219 this.subqueryType = ((Integer ) subqueryType).intValue(); 220 221 226 underTopAndNode = false; 227 this.leftOperand = (ValueNode) leftOperand; 228 } 229 230 236 237 public String toString() 238 { 239 if (SanityManager.DEBUG) 240 { 241 return "subqueryType: " + subqueryType + "\n" + 242 "underTopAndNode: " + underTopAndNode + "\n" + 243 "subqueryNumber: " + subqueryNumber + "\n" + 244 "pointOfAttachment: " + pointOfAttachment + "\n" + 245 "preprocessed: " + preprocessed + "\n" + 246 "distinctExpression: " + distinctExpression + "\n" + 247 super.toString(); 248 } 249 else 250 { 251 return ""; 252 } 253 } 254 255 261 262 public void printSubNodes(int depth) 263 { 264 if (SanityManager.DEBUG) 265 { 266 super.printSubNodes(depth); 267 268 if (resultSet != null) 269 { 270 printLabel(depth, "resultSet: "); 271 resultSet.treePrint(depth + 1); 272 } 273 274 if (leftOperand != null) 275 { 276 printLabel(depth, "leftOperand: "); 277 leftOperand.treePrint(depth + 1); 278 } 279 } 280 } 281 282 287 public ResultSetNode getResultSet() 288 { 289 return resultSet; 290 } 291 292 297 public int getSubqueryType() 298 { 299 return subqueryType; 300 } 301 302 307 public void setSubqueryType(int subqueryType) 308 { 309 this.subqueryType = subqueryType; 310 } 311 312 319 public void setPointOfAttachment(int pointOfAttachment) 320 throws StandardException 321 { 322 325 if (! isMaterializable()) 326 { 327 this.pointOfAttachment = pointOfAttachment; 328 } 329 } 330 331 338 public boolean getUnderTopAndNode() 339 { 340 return underTopAndNode; 341 } 342 343 348 public int getPointOfAttachment() 349 { 350 if (SanityManager.DEBUG) 351 { 352 SanityManager.ASSERT(pointOfAttachment >= 0, 353 "pointOfAttachment expected to be >= 0"); 354 } 355 return pointOfAttachment; 356 } 357 358 365 boolean getPreprocessed() 366 { 367 return preprocessed; 368 } 369 370 376 void setParentComparisonOperator(BinaryComparisonOperatorNode parent) 377 { 378 parentComparisonOperator = parent; 379 } 380 381 389 public ValueNode remapColumnReferencesToExpressions() 390 throws StandardException 391 { 392 395 if (resultSet instanceof SelectNode) 396 { 397 ResultColumnList selectRCL = resultSet.getResultColumns(); 398 SelectNode select = (SelectNode) resultSet; 399 PredicateList selectPL = select.getWherePredicates(); 400 401 if (SanityManager.DEBUG) 402 { 403 SanityManager.ASSERT(selectPL != null, 404 "selectPL expected to be non-null"); 405 } 406 selectRCL.remapColumnReferencesToExpressions(); 407 selectPL.remapColumnReferencesToExpressions(); 408 } 409 return this; 410 } 411 412 427 public ValueNode bindExpression(FromList fromList, SubqueryList subqueryList, 428 Vector aggregateVector) 429 throws StandardException 430 { 431 ResultColumnList resultColumns; 432 433 checkReliability( CompilerContext.SUBQUERY_ILLEGAL, SQLState.LANG_SUBQUERY ); 435 436 resultColumns = resultSet.getResultColumns(); 437 438 441 if (resultColumns.size() != 1) 442 { 443 throw StandardException.newException(SQLState.LANG_NON_SINGLE_COLUMN_SUBQUERY); 444 } 445 446 452 resultSet.verifySelectStarSubquery(fromList, subqueryType); 453 454 465 if (subqueryType == EXISTS_SUBQUERY) 466 { 467 468 resultSet.setResultToBooleanTrueNode(true); 469 } 470 471 475 CompilerContext cc = getCompilerContext(); 476 477 resultSet = resultSet.bindNonVTITables(getDataDictionary(), fromList); 478 resultSet = resultSet.bindVTITables(fromList); 479 480 481 if (subqueryNumber == -1) 482 subqueryNumber = cc.getNextSubqueryNumber(); 483 484 485 resultSet.rejectParameters(); 486 487 if (subqueryType == EXISTS_SUBQUERY) 488 { 489 490 resultSet.bindTargetExpressions(fromList); 491 492 498 resultSet.setResultToBooleanTrueNode(false); 499 } 500 501 502 if (leftOperand != null) 503 { 504 leftOperand = leftOperand.bindExpression(fromList, subqueryList, 505 aggregateVector); 506 } 507 508 509 resultSet.bindExpressions(fromList); 510 511 resultSet.bindResultColumns(fromList); 512 513 516 resultColumns = resultSet.getResultColumns(); 517 518 522 if (leftOperand != null && leftOperand.requiresTypeFromContext()) 523 { 524 leftOperand.setType( 525 ((ResultColumn) resultColumns.elementAt(0)).getTypeServices()); 526 } 527 528 setDataTypeServices(resultColumns); 530 531 532 subqueryList.addSubqueryNode(this); 533 534 return this; 535 } 536 537 552 public ValueNode preprocess(int numTables, 553 FromList outerFromList, 554 SubqueryList outerSubqueryList, 555 PredicateList outerPredicateList) 556 throws StandardException 557 { 558 561 if (preprocessed) 562 { 563 return this; 564 } 565 preprocessed = true; 566 567 boolean flattenable; 568 ValueNode topNode = this; 569 570 resultSet = resultSet.preprocess(numTables, null, (FromList) null); 571 572 if (resultSet instanceof SelectNode) 574 { 575 if (((SelectNode) resultSet).hasDistinct()) 576 { 577 ((SelectNode) resultSet).clearDistinct(); 578 581 if (subqueryType == EXPRESSION_SUBQUERY) 582 { 583 distinctExpression = true; 584 } 585 } 586 } 587 588 600 if ((isIN() || isANY()) && 601 resultSet.returnsAtMostOneRow()) 602 { 603 if (! hasCorrelatedCRs()) 604 { 605 changeToCorrespondingExpressionType(); 606 } 607 } 608 609 613 614 619 flattenable = (resultSet instanceof RowResultSetNode) && 620 underTopAndNode && 621 parentComparisonOperator instanceof BinaryComparisonOperatorNode; 622 if (flattenable) 623 { 624 629 leftOperand = parentComparisonOperator.getLeftOperand(); 630 RowResultSetNode rrsn = (RowResultSetNode) resultSet; 632 FromList fl = new FromList(); 633 634 outerSubqueryList.removeElement(this); 636 637 641 if (rrsn.subquerys.size() != 0) 642 { 643 fl.addElement(rrsn); 644 outerFromList.destructiveAppend(fl); 645 } 646 647 650 outerSubqueryList.destructiveAppend(rrsn.subquerys); 651 652 661 ValueNode rightOperand; 662 rightOperand = ((ResultColumn) rrsn.getResultColumns().elementAt(0)). 663 getExpression(); 664 return getNewJoinCondition(leftOperand, rightOperand); 665 } 666 667 681 boolean flattenableNotExists = (isNOT_EXISTS() || canAllBeFlattened()); 682 683 flattenable = (resultSet instanceof SelectNode) && 684 underTopAndNode && 685 (isIN() || isANY() || isEXISTS() || flattenableNotExists || 686 parentComparisonOperator != null); 687 688 if (flattenable) 689 { 690 SelectNode select = (SelectNode) resultSet; 691 if ((select.getAggregateVector(IN_SELECT_LIST).size() == 0) && 692 (! select.getGeneratedForGroupbyClause())) 693 { 694 ValueNode origLeftOperand = leftOperand; 695 696 697 700 boolean additionalEQ = 701 (subqueryType == IN_SUBQUERY) || 702 (subqueryType == EQ_ANY_SUBQUERY); 703 704 705 additionalEQ = additionalEQ && 706 ((leftOperand instanceof ConstantNode) || 707 (leftOperand instanceof ColumnReference) || 708 (leftOperand.requiresTypeFromContext())); 709 714 if (parentComparisonOperator instanceof BinaryComparisonOperatorNode) 715 { 716 leftOperand = parentComparisonOperator.getLeftOperand(); 717 } 718 720 if ((! flattenableNotExists) && select.uniqueSubquery(additionalEQ)) 721 { 722 return flattenToNormalJoin(numTables, 724 outerFromList, outerSubqueryList, 725 outerPredicateList); 726 } 727 744 else if ( (isIN() || isANY() || isEXISTS() || flattenableNotExists) && 745 ((leftOperand == null) ? true : 746 leftOperand.categorize(new JBitSet(numTables), false)) && 747 select.getWherePredicates().allPushable() && 748 singleFromBaseTable(select.getFromList())) 749 { 750 return flattenToExistsJoin(numTables, 751 outerFromList, outerSubqueryList, 752 outerPredicateList, flattenableNotExists); 753 } 754 755 leftOperand = origLeftOperand; 757 } 758 } 759 760 769 if (leftOperand != null) 770 { 771 topNode = pushNewPredicate(numTables); 772 pushedNewPredicate = true; 773 } 774 777 else if (subqueryType == NOT_EXISTS_SUBQUERY) 778 { 779 topNode = genIsNullTree(); 780 subqueryType = EXISTS_SUBQUERY; 781 } 782 783 788 isInvariant(); 789 hasCorrelatedCRs(); 790 791 800 if (parentComparisonOperator != null) 801 { 802 parentComparisonOperator.setRightOperand(topNode); 803 return parentComparisonOperator; 804 } 805 806 return topNode; 807 } 808 809 818 private boolean singleFromBaseTable(FromList fromList) 819 { 820 boolean retCode = (fromList.size() == 1); 821 822 if (retCode) 823 { 824 FromTable ft = (FromTable) fromList.elementAt(0); 825 826 if (((ft instanceof ProjectRestrictNode) && 827 ((ProjectRestrictNode) ft).getChildResult() instanceof FromBaseTable) || 828 ft instanceof FromBaseTable) 829 { 830 } 831 else 832 { 833 retCode = false; 834 } 835 } 836 837 return retCode; 838 } 839 840 846 private boolean canAllBeFlattened () throws StandardException 847 { 848 boolean result = false; 849 if (isNOT_IN() || isALL()) 850 { 851 ValueNode rightOperand = ((ResultColumn) resultSet.getResultColumns().elementAt(0)). 852 getExpression(); 853 result = (! leftOperand.getTypeServices().isNullable() && 854 ! rightOperand.getTypeServices().isNullable()); 855 } 856 return result; 857 } 858 859 897 private ValueNode flattenToNormalJoin(int numTables, 898 FromList outerFromList, 899 SubqueryList outerSubqueryList, 900 PredicateList outerPredicateList) 901 throws StandardException 902 { 903 SelectNode select = (SelectNode) resultSet; 904 FromList fl = select.getFromList(); 905 int[] tableNumbers = fl.getTableNumbers(); 906 907 outerSubqueryList.removeElement(this); 909 910 913 select.decrementLevel(1); 914 915 916 outerFromList.destructiveAppend(fl); 917 918 921 outerPredicateList.destructiveAppend(select.getWherePredicates()); 922 923 929 outerSubqueryList.destructiveAppend(select.getWhereSubquerys()); 930 outerSubqueryList.destructiveAppend(select.getSelectSubquerys()); 931 932 941 if (leftOperand == null) 942 { 943 return (ValueNode) getNodeFactory().getNode( 944 C_NodeTypes.BOOLEAN_CONSTANT_NODE, 945 Boolean.TRUE, 946 getContextManager()); 947 } 948 else 949 { 950 ValueNode rightOperand; 951 rightOperand = ((ResultColumn) select.getResultColumns().elementAt(0)). 952 getExpression(); 953 957 if (rightOperand instanceof ColumnReference) 958 { 959 ColumnReference cr = (ColumnReference) rightOperand; 960 int tableNumber = cr.getTableNumber(); 961 for (int index = 0; index < tableNumbers.length; index++) 962 { 963 if (tableNumber == tableNumbers[index]) 964 { 965 cr.setSourceLevel( 966 cr.getSourceLevel() - 1); 967 break; 968 } 969 } 970 } 971 return getNewJoinCondition(leftOperand, rightOperand); 972 } 973 } 974 975 997 private ValueNode flattenToExistsJoin(int numTables, 998 FromList outerFromList, 999 SubqueryList outerSubqueryList, 1000 PredicateList outerPredicateList, 1001 boolean flattenableNotExists) 1002 throws StandardException 1003 { 1004 SelectNode select = (SelectNode) resultSet; 1005 1006 select.getFromList().genExistsBaseTables(resultSet.getReferencedTableMap(), 1008 outerFromList, flattenableNotExists); 1009 1010 1024 1025 return flattenToNormalJoin(numTables, outerFromList, 1026 outerSubqueryList, outerPredicateList); 1027 } 1028 1029 1038 private boolean isInvariant() throws StandardException 1039 { 1040 if (doneInvariantCheck) 1041 { 1042 return !foundVariant; 1043 } 1044 1045 doneInvariantCheck = true; 1046 HasVariantValueNodeVisitor visitor = new HasVariantValueNodeVisitor(); 1047 resultSet.accept(visitor); 1048 foundVariant = visitor.hasVariant(); 1049 return !foundVariant; 1050 } 1051 1052 1061 public boolean hasCorrelatedCRs() throws StandardException 1062 { 1063 if (doneCorrelationCheck) 1064 { 1065 return foundCorrelation; 1066 } 1067 doneCorrelationCheck = true; 1068 1069 ResultSetNode realSubquery = resultSet; 1070 ResultColumnList oldRCL = null; 1071 1072 1077 if (pushedNewPredicate) 1078 { 1079 if (SanityManager.DEBUG) 1080 { 1081 SanityManager.ASSERT(resultSet instanceof ProjectRestrictNode, 1082 "resultSet expected to be a ProjectRestrictNode!"); 1083 } 1084 1085 realSubquery = ((ProjectRestrictNode) resultSet).getChildResult(); 1086 oldRCL = realSubquery.getResultColumns(); 1087 1088 1090 if (oldRCL.size() > 1) 1091 { 1092 ResultColumnList newRCL = new ResultColumnList(); 1093 newRCL.addResultColumn(oldRCL.getResultColumn(1)); 1094 realSubquery.setResultColumns(newRCL); 1095 } 1096 } 1097 1098 HasCorrelatedCRsVisitor visitor = new HasCorrelatedCRsVisitor(); 1099 realSubquery.accept(visitor); 1100 foundCorrelation = visitor.hasCorrelatedCRs(); 1101 1102 if (pushedNewPredicate && (oldRCL.size() > 1)) 1103 { 1104 realSubquery.setResultColumns(oldRCL); 1105 } 1106 1107 return foundCorrelation; 1108 } 1109 1110 1148 private UnaryComparisonOperatorNode pushNewPredicate( 1149 int numTables) 1150 throws StandardException 1151 { 1152 AndNode andNode; 1153 BinaryComparisonOperatorNode bcoNode = null; 1154 JBitSet tableMap; 1155 Predicate predicate; 1156 ResultColumn firstRC; 1157 ResultColumnList resultColumns; 1158 UnaryComparisonOperatorNode ucoNode = null; 1159 ValueNode oldWhereClause; 1160 ValueNode rightOperand; 1161 1162 1165 resultSet = resultSet.ensurePredicateList(numTables); 1166 1167 1170 resultColumns = resultSet.getResultColumns(); 1171 1172 1177 ResultColumnList newRCL = resultColumns.copyListAndObjects(); 1178 newRCL.genVirtualColumnNodes(resultSet, resultColumns); 1179 resultSet = (ResultSetNode) getNodeFactory().getNode( 1180 C_NodeTypes.PROJECT_RESTRICT_NODE, 1181 resultSet, newRCL, null, null, null, null, null, 1188 getContextManager()); 1189 resultColumns = newRCL; 1190 1191 firstRC = (ResultColumn) resultColumns.elementAt(0); 1192 rightOperand = firstRC.getExpression(); 1193 1194 bcoNode = getNewJoinCondition(leftOperand, rightOperand); 1195 1196 ValueNode andLeft = bcoNode; 1197 1198 1207 if (isNOT_IN() || isALL()) 1208 { 1209 boolean leftNullable = leftOperand.getTypeServices().isNullable(); 1210 boolean rightNullable = rightOperand.getTypeServices().isNullable(); 1211 if (leftNullable || rightNullable) 1212 { 1213 1215 BooleanConstantNode falseNode = (BooleanConstantNode) getNodeFactory().getNode( 1216 C_NodeTypes.BOOLEAN_CONSTANT_NODE, 1217 Boolean.FALSE, 1218 getContextManager()); 1219 OrNode newOr = (OrNode) getNodeFactory().getNode( 1220 C_NodeTypes.OR_NODE, 1221 bcoNode, 1222 falseNode, 1223 getContextManager()); 1224 newOr.postBindFixup(); 1225 andLeft = newOr; 1226 1227 if (leftNullable) 1228 { 1229 UnaryComparisonOperatorNode leftIsNull = (UnaryComparisonOperatorNode) 1230 getNodeFactory().getNode( 1231 C_NodeTypes.IS_NULL_NODE, 1232 leftOperand, 1233 getContextManager()); 1234 leftIsNull.bindComparisonOperator(); 1235 newOr = (OrNode) getNodeFactory().getNode( 1236 C_NodeTypes.OR_NODE, 1237 leftIsNull, 1238 andLeft, 1239 getContextManager()); 1240 newOr.postBindFixup(); 1241 andLeft = newOr; 1242 } 1243 if (rightNullable) 1244 { 1245 UnaryComparisonOperatorNode rightIsNull = (UnaryComparisonOperatorNode) 1246 getNodeFactory().getNode( 1247 C_NodeTypes.IS_NULL_NODE, 1248 rightOperand, 1249 getContextManager()); 1250 rightIsNull.bindComparisonOperator(); 1251 newOr = (OrNode) getNodeFactory().getNode( 1252 C_NodeTypes.OR_NODE, 1253 rightIsNull, 1254 andLeft, 1255 getContextManager()); 1256 newOr.postBindFixup(); 1257 andLeft = newOr; 1258 } 1259 } 1260 } 1261 1262 1263 andNode = (AndNode) getNodeFactory().getNode( 1264 C_NodeTypes.AND_NODE, 1265 andLeft, 1266 getTrueNode(), 1267 getContextManager()); 1268 1269 1270 tableMap = new JBitSet(numTables); 1271 andNode.postBindFixup(); 1272 1273 1274 predicate = (Predicate) getNodeFactory().getNode( 1275 C_NodeTypes.PREDICATE, 1276 andNode, 1277 tableMap, 1278 getContextManager()); 1279 predicate.categorize(); 1280 1281 1282 resultSet = resultSet.addNewPredicate(predicate); 1283 1284 1285 leftOperand = null; 1286 firstRC.setType(getTypeServices()); 1287 firstRC.setExpression(getTrueNode()); 1288 1289 1290 switch (subqueryType) 1291 { 1292 case IN_SUBQUERY: 1293 case EQ_ANY_SUBQUERY: 1294 case NE_ANY_SUBQUERY: 1295 case LE_ANY_SUBQUERY: 1296 case LT_ANY_SUBQUERY: 1297 case GE_ANY_SUBQUERY: 1298 case GT_ANY_SUBQUERY: 1299 ucoNode = (UnaryComparisonOperatorNode) 1300 getNodeFactory().getNode( 1301 C_NodeTypes.IS_NOT_NULL_NODE, 1302 this, 1303 getContextManager()); 1304 break; 1305 1306 case NOT_IN_SUBQUERY: 1307 case EQ_ALL_SUBQUERY: 1308 case NE_ALL_SUBQUERY: 1309 case LE_ALL_SUBQUERY: 1310 case LT_ALL_SUBQUERY: 1311 case GE_ALL_SUBQUERY: 1312 case GT_ALL_SUBQUERY: 1313 ucoNode = (UnaryComparisonOperatorNode) 1314 getNodeFactory().getNode( 1315 C_NodeTypes.IS_NULL_NODE, 1316 this, 1317 getContextManager()); 1318 break; 1319 } 1320 ucoNode.bindComparisonOperator(); 1321 return ucoNode; 1322 } 1323 1324 1334 private BinaryComparisonOperatorNode getNewJoinCondition( 1335 ValueNode leftOperand, 1336 ValueNode rightOperand) 1337 throws StandardException 1338 { 1339 BinaryComparisonOperatorNode bcoNode = null; 1340 1341 1347 int operatorType = subqueryType; 1348 if (subqueryType == EXPRESSION_SUBQUERY) 1349 { 1350 if (SanityManager.DEBUG) 1351 { 1352 SanityManager.ASSERT(parentComparisonOperator != null, 1353 "parentComparisonOperator expected to be non-null"); 1354 } 1355 1356 int parentOperator = -1; 1357 1358 if (parentComparisonOperator.isRelationalOperator()) 1359 { 1360 RelationalOperator ro = (RelationalOperator)parentComparisonOperator; 1361 parentOperator = ro.getOperator(); 1362 } 1363 1364 if (parentOperator == RelationalOperator.EQUALS_RELOP) 1365 { 1366 operatorType = EQ_ANY_SUBQUERY; 1367 } 1368 else if (parentOperator == RelationalOperator.NOT_EQUALS_RELOP) 1369 { 1370 operatorType = NE_ANY_SUBQUERY; 1371 } 1372 else if (parentOperator == RelationalOperator.LESS_EQUALS_RELOP) 1373 { 1374 operatorType = LE_ANY_SUBQUERY; 1375 } 1376 else if (parentOperator == RelationalOperator.LESS_THAN_RELOP) 1377 { 1378 operatorType = LT_ANY_SUBQUERY; 1379 } 1380 else if (parentOperator == RelationalOperator.GREATER_EQUALS_RELOP) 1381 { 1382 operatorType = GE_ANY_SUBQUERY; 1383 } 1384 else if (parentOperator == RelationalOperator.GREATER_THAN_RELOP) 1385 { 1386 operatorType = GT_ANY_SUBQUERY; 1387 } 1388 } 1389 1390 int bcoType = 0; 1391 int nodeType = 0; 1392 1393 1394 switch (operatorType) 1395 { 1396 case IN_SUBQUERY: 1397 case EQ_ANY_SUBQUERY: 1398 case NOT_IN_SUBQUERY: 1399 case NE_ALL_SUBQUERY: 1400 nodeType = C_NodeTypes.BINARY_EQUALS_OPERATOR_NODE; 1401 break; 1402 1403 case NE_ANY_SUBQUERY: 1404 case EQ_ALL_SUBQUERY: 1405 nodeType = C_NodeTypes.BINARY_NOT_EQUALS_OPERATOR_NODE; 1406 break; 1407 1408 case LE_ANY_SUBQUERY: 1409 case GT_ALL_SUBQUERY: 1410 nodeType = C_NodeTypes.BINARY_LESS_EQUALS_OPERATOR_NODE; 1411 break; 1412 1413 case LT_ANY_SUBQUERY: 1414 case GE_ALL_SUBQUERY: 1415 nodeType = C_NodeTypes.BINARY_LESS_THAN_OPERATOR_NODE; 1416 break; 1417 1418 case GE_ANY_SUBQUERY: 1419 case LT_ALL_SUBQUERY: 1420 nodeType = C_NodeTypes.BINARY_GREATER_EQUALS_OPERATOR_NODE; 1421 break; 1422 1423 case GT_ANY_SUBQUERY: 1424 case LE_ALL_SUBQUERY: 1425 nodeType = C_NodeTypes.BINARY_GREATER_THAN_OPERATOR_NODE; 1426 break; 1427 1428 default: 1429 if (SanityManager.DEBUG) 1430 SanityManager.ASSERT(false, 1431 "subqueryType (" + subqueryType + ") is an unexpected type"); 1432 } 1433 1434 bcoNode = (BinaryComparisonOperatorNode) 1435 getNodeFactory().getNode( 1436 nodeType, 1437 leftOperand, 1438 rightOperand, 1439 getContextManager()); 1440 1441 bcoNode.bindComparisonOperator(); 1442 return bcoNode; 1443 } 1444 1445 1446 1462 ValueNode eliminateNots(boolean underNotNode) 1463 throws StandardException 1464 { 1465 ValueNode result = this; 1466 1467 if (underNotNode) 1468 { 1469 1472 1475 switch (subqueryType) 1476 { 1477 case EXPRESSION_SUBQUERY: 1478 result = genEqualsFalseTree(); 1479 break; 1480 1481 case EXISTS_SUBQUERY: 1482 subqueryType = NOT_EXISTS_SUBQUERY; 1483 break; 1484 1485 1486 case IN_SUBQUERY: 1487 case EQ_ANY_SUBQUERY: 1488 subqueryType = NOT_IN_SUBQUERY; 1489 break; 1490 1491 case NE_ANY_SUBQUERY: 1492 subqueryType = EQ_ALL_SUBQUERY; 1493 break; 1494 1495 case GE_ANY_SUBQUERY: 1496 subqueryType = LT_ALL_SUBQUERY; 1497 break; 1498 1499 case GT_ANY_SUBQUERY: 1500 subqueryType = LE_ALL_SUBQUERY; 1501 break; 1502 1503 case LE_ANY_SUBQUERY: 1504 subqueryType = GT_ALL_SUBQUERY; 1505 break; 1506 1507 case LT_ANY_SUBQUERY: 1508 subqueryType = GE_ALL_SUBQUERY; 1509 break; 1510 1511 1514 case EQ_ALL_SUBQUERY: 1515 subqueryType = NE_ANY_SUBQUERY; 1516 break; 1517 1518 case NE_ALL_SUBQUERY: 1519 subqueryType = EQ_ANY_SUBQUERY; 1520 break; 1521 1522 case GE_ALL_SUBQUERY: 1523 subqueryType = LT_ANY_SUBQUERY; 1524 break; 1525 1526 case GT_ALL_SUBQUERY: 1527 subqueryType = LE_ANY_SUBQUERY; 1528 break; 1529 1530 case LE_ALL_SUBQUERY: 1531 subqueryType = GT_ANY_SUBQUERY; 1532 break; 1533 1534 case LT_ALL_SUBQUERY: 1535 subqueryType = GE_ANY_SUBQUERY; 1536 break; 1537 1538 default: 1539 if (SanityManager.DEBUG) 1540 SanityManager.ASSERT(false, 1541 "NOT is not supported for this time of subquery"); 1542 } 1543 } 1544 1545 1546 return result; 1547 } 1548 1549 1577 public ValueNode changeToCNF(boolean underTopAndNode) 1578 throws StandardException 1579 { 1580 1584 this.underTopAndNode = underTopAndNode; 1585 1586 1587 return this; 1588 } 1589 1590 1612 public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly) 1613 throws StandardException 1614 { 1615 1619 if (simplePredsOnly) 1620 { 1621 return false; 1622 } 1623 1624 1625 1626 1627 1628 1629 1630 1635 return isMaterializable(); 1636 1637 } 1638 1639 1644 boolean isMaterializable() throws StandardException 1645 { 1646 boolean retval = (subqueryType == EXPRESSION_SUBQUERY) && 1647 !hasCorrelatedCRs() && 1648 isInvariant(); 1649 1653 if (retval) 1654 { 1655 if (resultSet instanceof SelectNode) 1656 { 1657 SelectNode select = (SelectNode) resultSet; 1658 FromList fromList = select.getFromList(); 1659 fromList.setLevel(0); 1660 } 1661 } 1662 1663 return retval; 1664 } 1665 1666 1675 1676 public void optimize(DataDictionary dataDictionary, double outerRows) 1677 throws StandardException 1678 { 1679 1682 1683 1684 resultSet = resultSet.optimize(dataDictionary, null, outerRows); 1685 } 1686 1687 1692 public void modifyAccessPaths() throws StandardException 1693 { 1694 resultSet = resultSet.modifyAccessPaths(); 1695 } 1696 1697 1711 protected int getOrderableVariantType() throws StandardException 1712 { 1713 1720 if (isInvariant()) 1721 { 1722 if (!hasCorrelatedCRs() && 1723 (subqueryType == EXPRESSION_SUBQUERY)) 1724 { 1725 return Qualifier.QUERY_INVARIANT; 1726 } 1727 else 1728 { 1729 return Qualifier.SCAN_INVARIANT; 1730 } 1731 } 1732 else 1733 { 1734 return Qualifier.VARIANT; 1735 } 1736 } 1737 1738 1747 1748 public void generateExpression( 1749 ExpressionClassBuilder expressionBuilder, 1750 MethodBuilder mbex) 1751 throws StandardException 1752 { 1753 CompilerContext cc = getCompilerContext(); 1754 String resultSetString; 1755 1756 1765 if (SanityManager.DEBUG) 1766 { 1767 SanityManager.ASSERT(expressionBuilder instanceof ActivationClassBuilder, 1768 "Expecting an ActivationClassBuilder"); 1769 } 1770 1771 ActivationClassBuilder acb = (ActivationClassBuilder) expressionBuilder; 1772 1773 1774 1775 if (subqueryType == EXPRESSION_SUBQUERY) 1776 { 1777 resultSetString = "getOnceResultSet"; 1778 } 1779 else 1780 { 1781 resultSetString = "getAnyResultSet"; 1782 } 1783 1784 CostEstimate costEstimate = resultSet.getFinalCostEstimate(); 1786 1787 1793 String subqueryTypeString = 1794 getTypeCompiler().interfaceName(); 1795 MethodBuilder mb = acb.newGeneratedFun(subqueryTypeString, Modifier.PROTECTED); 1796 1797 1798 LocalField rsFieldLF = acb.newFieldDeclaration(Modifier.PRIVATE, ClassName.NoPutResultSet); 1799 1800 ResultSetNode subNode = null; 1801 1802 if (!isMaterializable()) 1803 { 1804 MethodBuilder executeMB = acb.getExecuteMethod(); 1805 if (pushedNewPredicate && (! hasCorrelatedCRs())) 1806 { 1807 1815 if (SanityManager.DEBUG) 1816 { 1817 SanityManager.ASSERT(resultSet instanceof ProjectRestrictNode, 1818 "resultSet expected to be a ProjectRestrictNode!"); 1819 } 1820 subNode = ((ProjectRestrictNode) resultSet).getChildResult(); 1821 LocalField subRS = acb.newFieldDeclaration(Modifier.PRIVATE, ClassName.NoPutResultSet); 1822 mb.getField(subRS); 1823 mb.conditionalIfNull(); 1824 1825 ResultSetNode materialSubNode = new MaterializeSubqueryNode(subRS); 1826 1827 materialSubNode.costEstimate = resultSet.getFinalCostEstimate(); 1829 1830 ((ProjectRestrictNode) resultSet).setChildResult(materialSubNode); 1831 1832 1835 subNode.generate(acb, mb); 1836 mb.startElseCode(); 1837 mb.getField(subRS); 1838 mb.completeConditional(); 1839 1840 mb.setField(subRS); 1841 1842 executeMB.pushNull( ClassName.NoPutResultSet); 1843 executeMB.setField(subRS); 1844 } 1845 1846 executeMB.pushNull( ClassName.NoPutResultSet); 1847 executeMB.setField(rsFieldLF); 1848 1849 mb.getField(rsFieldLF); 1851 mb.conditionalIfNull(); 1852 } 1853 1854 acb.pushGetResultSetFactoryExpression(mb); 1855 1856 int nargs; 1858 1859 1861 resultSet.generate(acb, mb); 1862 1863 1866 int subqResultSetNumber = cc.getNextResultSetNumber(); 1867 1868 1874 resultSet.getResultColumns().setResultSetNumber(subqResultSetNumber); 1875 1876 1877 resultSet.getResultColumns().generateNulls(acb, mb); 1878 1879 1886 if (subqueryType == EXPRESSION_SUBQUERY) 1887 { 1888 int cardinalityCheck; 1889 1890 1897 if (distinctExpression) 1898 { 1899 cardinalityCheck = OnceResultSet.UNIQUE_CARDINALITY_CHECK; 1900 } 1901 else if (resultSet.returnsAtMostOneRow()) 1902 { 1903 cardinalityCheck = OnceResultSet.NO_CARDINALITY_CHECK; 1904 } 1905 else 1906 { 1907 cardinalityCheck = OnceResultSet.DO_CARDINALITY_CHECK; 1908 } 1909 1910 1916 mb.push(cardinalityCheck); 1917 nargs = 8; 1918 1919 } else { 1920 nargs = 7; 1921 } 1922 1923 mb.push(subqResultSetNumber); 1924 mb.push(subqueryNumber); 1925 mb.push(pointOfAttachment); 1926 mb.push(costEstimate.rowCount()); 1927 mb.push(costEstimate.getEstimatedCost()); 1928 1929 mb.callMethod(VMOpcode.INVOKEINTERFACE, (String ) null, resultSetString, ClassName.NoPutResultSet, nargs); 1930 1931 1932 1933 1964 1965 1969 if (!isMaterializable()) 1970 { 1971 1973 if (pushedNewPredicate && (! hasCorrelatedCRs())) 1974 ((ProjectRestrictNode) resultSet).setChildResult(subNode); 1975 1976 mb.startElseCode(); 1978 mb.getField(rsFieldLF); 1979 mb.completeConditional(); 1980 } 1981 1982 mb.setField(rsFieldLF); 1983 1984 1985 mb.getField(rsFieldLF); 1986 mb.callMethod(VMOpcode.INVOKEINTERFACE, (String ) null, "openCore", "void", 0); 1987 1988 1989 mb.getField(rsFieldLF); 1990 mb.callMethod(VMOpcode.INVOKEINTERFACE, (String ) null, "getNextRowCore", ClassName.ExecRow, 0); 1991 1994 1995 mb.push(1); mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Row, "getColumn", ClassName.DataValueDescriptor, 1); 1998 mb.cast(subqueryTypeString); 1999 2002 2006 if (isMaterializable()) 2007 { 2008 2009 mb.getField(rsFieldLF); 2010 mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.ResultSet, "close", "void", 0); 2011 } 2012 2013 2014 mb.methodReturn(); 2016 mb.complete(); 2017 2018 2023 if (isMaterializable()) 2024 { 2025 LocalField lf = generateMaterialization(acb, mb, subqueryTypeString); 2026 mbex.getField(lf); 2027 2028 } else { 2029 2030 mbex.pushThis(); 2031 mbex.callMethod(VMOpcode.INVOKEVIRTUAL, (String ) null, mb.getName(), subqueryTypeString, 0); 2032 } 2033 } 2034 2035 2065 private LocalField generateMaterialization( 2066 ActivationClassBuilder acb, 2067 MethodBuilder mbsq, 2068 String type) 2069 { 2070 MethodBuilder mb = acb.executeMethod; 2071 2072 LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE, type); 2074 2075 2076 mb.pushThis(); 2077 mb.callMethod(VMOpcode.INVOKEVIRTUAL, (String ) null, mbsq.getName(), type, 0); 2078 2079 mb.setField(field); 2081 2082 return field; 2083 } 2084 2085 2086 private BooleanConstantNode getTrueNode() 2087 throws StandardException 2088 { 2089 if (trueNode == null) 2090 { 2091 trueNode = (BooleanConstantNode) getNodeFactory().getNode( 2092 C_NodeTypes.BOOLEAN_CONSTANT_NODE, 2093 Boolean.TRUE, 2094 getContextManager()); 2095 } 2096 return trueNode; 2097 } 2098 2099 2107 public Visitable accept(Visitor v) 2108 throws StandardException 2109 { 2110 Visitable returnNode = v.visit(this); 2111 2112 2114 if ((v instanceof HasCorrelatedCRsVisitor) && doneCorrelationCheck) 2115 { 2116 ((HasCorrelatedCRsVisitor) v).setHasCorrelatedCRs(foundCorrelation); 2117 return returnNode; 2118 } 2119 2120 if (v.skipChildren(this)) 2121 { 2122 return returnNode; 2123 } 2124 2125 if (resultSet != null && !v.stopTraversal()) 2126 { 2127 resultSet = (ResultSetNode)resultSet.accept(v); 2128 } 2129 2130 if (leftOperand != null && !v.stopTraversal()) 2131 { 2132 leftOperand = (ValueNode)leftOperand.accept(v); 2133 } 2134 return returnNode; 2135 } 2136 2137 private boolean isIN() 2138 { 2139 return subqueryType == IN_SUBQUERY; 2140 } 2141 2142 private boolean isNOT_IN() 2143 { 2144 return subqueryType == NOT_IN_SUBQUERY; 2145 } 2146 2147 private boolean isANY() 2148 { 2149 switch (subqueryType) 2150 { 2151 case EQ_ANY_SUBQUERY: 2152 case NE_ANY_SUBQUERY: 2153 case LE_ANY_SUBQUERY: 2154 case LT_ANY_SUBQUERY: 2155 case GE_ANY_SUBQUERY: 2156 case GT_ANY_SUBQUERY: 2157 return true; 2158 2159 default: 2160 return false; 2161 } 2162 } 2163 2164 private boolean isALL() 2165 { 2166 switch (subqueryType) 2167 { 2168 case EQ_ALL_SUBQUERY: 2169 case NE_ALL_SUBQUERY: 2170 case LE_ALL_SUBQUERY: 2171 case LT_ALL_SUBQUERY: 2172 case GE_ALL_SUBQUERY: 2173 case GT_ALL_SUBQUERY: 2174 return true; 2175 2176 default: 2177 return false; 2178 } 2179 } 2180 2181 private boolean isEXISTS() 2182 { 2183 return subqueryType == EXISTS_SUBQUERY; 2184 } 2185 2186 private boolean isNOT_EXISTS() 2187 { 2188 return subqueryType == NOT_EXISTS_SUBQUERY; 2189 } 2190 2191 2197 private void changeToCorrespondingExpressionType() 2198 throws StandardException 2199 { 2200 BinaryOperatorNode bcon = null; 2201 2202 switch (subqueryType) 2203 { 2204 case EQ_ANY_SUBQUERY: 2205 case IN_SUBQUERY: 2206 bcon = (BinaryOperatorNode) getNodeFactory().getNode( 2207 C_NodeTypes.BINARY_EQUALS_OPERATOR_NODE, 2208 leftOperand, 2209 this, 2210 getContextManager()); 2211 break; 2212 2213 case NE_ANY_SUBQUERY: 2214 bcon = (BinaryOperatorNode) getNodeFactory().getNode( 2215 C_NodeTypes.BINARY_NOT_EQUALS_OPERATOR_NODE, 2216 leftOperand, 2217 this, 2218 getContextManager()); 2219 break; 2220 2221 case LE_ANY_SUBQUERY: 2222 bcon = (BinaryOperatorNode) getNodeFactory().getNode( 2223 C_NodeTypes.BINARY_LESS_EQUALS_OPERATOR_NODE, 2224 leftOperand, 2225 this, 2226 getContextManager()); 2227 break; 2228 2229 case LT_ANY_SUBQUERY: 2230 bcon = (BinaryOperatorNode) getNodeFactory().getNode( 2231 C_NodeTypes.BINARY_LESS_THAN_OPERATOR_NODE, 2232 leftOperand, 2233 this, 2234 getContextManager()); 2235 break; 2236 2237 case GE_ANY_SUBQUERY: 2238 bcon = (BinaryOperatorNode) getNodeFactory().getNode( 2239 C_NodeTypes.BINARY_GREATER_EQUALS_OPERATOR_NODE, 2240 leftOperand, 2241 this, 2242 getContextManager()); 2243 break; 2244 2245 case GT_ANY_SUBQUERY: 2246 bcon = (BinaryOperatorNode) getNodeFactory().getNode( 2247 C_NodeTypes.BINARY_GREATER_THAN_OPERATOR_NODE, 2248 leftOperand, 2249 this, 2250 getContextManager()); 2251 break; 2252 } 2253 2254 subqueryType = EXPRESSION_SUBQUERY; 2256 setDataTypeServices(resultSet.getResultColumns()); 2257 2258 parentComparisonOperator = (BinaryComparisonOperatorNode) bcon; 2259 2260 parentComparisonOperator.bindComparisonOperator(); 2261 leftOperand = null; 2262 } 2263 2264 private void setDataTypeServices(ResultColumnList resultColumns) 2265 throws StandardException 2266 { 2267 DataTypeDescriptor dts; 2268 2269 2277 if (subqueryType == EXPRESSION_SUBQUERY) 2278 { 2279 dts = ((ResultColumn) resultColumns.elementAt(0)).getTypeServices(); 2280 } 2281 else 2282 { 2283 dts = getTrueNode().getTypeServices(); 2284 } 2285 2286 2289 if (! dts.isNullable()) 2290 { 2291 dts = new DataTypeDescriptor(dts, true); 2292 } 2293 setType(dts); 2294 } 2295 2296 2299 protected boolean isEquivalent(ValueNode o) 2300 { 2301 return false; 2302 } 2303} 2304 | Popular Tags |