1 21 22 23 package org.apache.derby.impl.sql.compile; 24 25 import org.apache.derby.iapi.sql.compile.CostEstimate; 26 import org.apache.derby.iapi.sql.compile.Optimizer; 27 import org.apache.derby.iapi.sql.compile.Visitable; 28 import org.apache.derby.iapi.sql.compile.Visitor; 29 import org.apache.derby.iapi.sql.compile.C_NodeTypes; 30 31 import org.apache.derby.iapi.sql.conn.Authorizer; 32 33 import org.apache.derby.iapi.sql.dictionary.DataDictionary; 34 import org.apache.derby.iapi.sql.dictionary.TableDescriptor; 35 36 import org.apache.derby.iapi.types.TypeId; 37 import org.apache.derby.iapi.types.DataTypeDescriptor; 38 39 import org.apache.derby.iapi.reference.Limits; 40 import org.apache.derby.iapi.reference.SQLState; 41 import org.apache.derby.iapi.error.StandardException; 42 43 import org.apache.derby.iapi.store.access.TransactionController; 44 45 import org.apache.derby.iapi.services.sanity.SanityManager; 46 47 import org.apache.derby.iapi.util.JBitSet; 48 49 import java.util.Vector ; 50 import java.util.HashSet ; 51 52 65 66 public class SelectNode extends ResultSetNode 67 { 68 71 FromList fromList; 72 FromTable targetTable; 73 74 75 Vector selectAggregates ; 76 Vector whereAggregates; 77 78 84 ValueNode whereClause; 85 ValueNode originalWhereClause; 86 87 90 GroupByList groupByList; 91 92 93 OrderByList orderByList; 94 boolean orderByQuery ; 95 96 97 PredicateList wherePredicates; 98 99 100 SubqueryList selectSubquerys; 101 SubqueryList whereSubquerys; 102 103 104 private boolean bindTargetListOnly; 105 106 private boolean isDistinct; 107 108 private boolean orderByAndDistinctMerged; 109 110 private boolean generatedForGroupByClause; 111 private boolean generatedForHavingClause; 112 113 114 private FromList preJoinFL; 115 116 128 129 public void init(Object selectList, 130 Object aggregateVector, 131 Object fromList, 132 Object whereClause, 133 Object groupByList) 134 throws StandardException 135 { 136 139 resultColumns = (ResultColumnList) selectList; 140 if (resultColumns != null) 141 resultColumns.markInitialSize(); 142 this.fromList = (FromList) fromList; 143 this.whereClause = (ValueNode) whereClause; 144 this.originalWhereClause = (ValueNode) whereClause; 145 this.groupByList = (GroupByList) groupByList; 146 bindTargetListOnly = false; 147 } 148 149 155 156 public String toString() 157 { 158 if (SanityManager.DEBUG) 159 { 160 return "isDistinct: "+ isDistinct + "\n"+ 161 "groupByList: " + 162 (groupByList != null ? groupByList.toString() : "null") + "\n" + 163 "orderByList: " + 164 (orderByList != null ? orderByList.toString() : "null") + "\n" + 165 "generatedForGroupByClause: " +generatedForGroupByClause +"\n" + 166 "generatedForHavingClause: " + generatedForHavingClause + "\n" + 167 super.toString(); 168 } 169 else 170 { 171 return ""; 172 } 173 } 174 175 public String statementToString() 176 { 177 return "SELECT"; 178 } 179 180 public void makeDistinct() 181 { 182 isDistinct = true; 183 } 184 185 public void clearDistinct() 186 { 187 isDistinct = false; 188 } 189 190 boolean hasDistinct() 191 { 192 return isDistinct; 193 } 194 195 198 public void markAsForGroupByClause() 199 { 200 generatedForGroupByClause = true; 201 } 202 203 208 public boolean getGeneratedForGroupbyClause() 209 { 210 return generatedForGroupByClause; 211 } 212 213 216 public void markAsForHavingClause() 217 { 218 generatedForHavingClause = true; 219 } 220 221 227 228 public void printSubNodes(int depth) 229 { 230 if (SanityManager.DEBUG) 231 { 232 super.printSubNodes(depth); 233 234 if (selectSubquerys != null) 235 { 236 printLabel(depth, "selectSubquerys: "); 237 selectSubquerys.treePrint(depth + 1); 238 } 239 240 printLabel(depth, "fromList: "); 241 242 if (fromList != null) 243 { 244 fromList.treePrint(depth + 1); 245 } 246 247 if (whereClause != null) 248 { 249 printLabel(depth, "whereClause: "); 250 whereClause.treePrint(depth + 1); 251 } 252 253 if ((wherePredicates != null) &&wherePredicates.size() > 0) 254 { 255 printLabel(depth, "wherePredicates: "); 256 wherePredicates.treePrint(depth + 1); 257 } 258 259 if (whereSubquerys != null) 260 { 261 printLabel(depth, "whereSubquerys: "); 262 whereSubquerys.treePrint(depth + 1); 263 } 264 265 printLabel(depth, "preJoinFL: "); 266 267 if (preJoinFL != null) 268 { 269 preJoinFL.treePrint(depth + 1); 270 } 271 } 272 } 273 274 279 public FromList getFromList() 280 { 281 return fromList; 282 } 283 284 295 public ColumnReference findColumnReferenceInResult(String colName) 296 throws StandardException 297 { 298 if (fromList.size() != 1) 299 return null; 300 301 FromTable ft = (FromTable) fromList.elementAt(0); 303 if (! ((ft instanceof ProjectRestrictNode) && 304 ((ProjectRestrictNode) ft).getChildResult() instanceof FromBaseTable) && 305 !(ft instanceof FromBaseTable)) 306 return null; 307 308 int rclSize = resultColumns.size(); 310 for (int index = 0; index < rclSize; index++) 311 { 312 ResultColumn rc = (ResultColumn) resultColumns.elementAt(index); 313 if (! (rc.getExpression() instanceof ColumnReference)) 314 return null; 315 316 ColumnReference crNode = (ColumnReference) rc.getExpression(); 317 318 if (crNode.columnName.equals(colName)) 319 return (ColumnReference) crNode.getClone(); 320 } 321 322 return null; 323 } 324 325 330 public ValueNode getWhereClause() 331 { 332 return whereClause; 333 } 334 335 340 public PredicateList getWherePredicates() 341 { 342 return wherePredicates; 343 } 344 345 350 public SubqueryList getSelectSubquerys() 351 { 352 return selectSubquerys; 353 } 354 355 362 public Vector getAggregateVector(int clause) 363 { 364 switch (clause) 365 { 366 case ValueNode.IN_SELECT_LIST: 367 return selectAggregates; 368 369 case ValueNode.IN_WHERE_CLAUSE: 370 if (generatedForHavingClause) 371 { 372 return null; 373 } 374 else 375 { 376 return whereAggregates; 377 } 378 379 case ValueNode.IN_HAVING_CLAUSE: 380 if (generatedForHavingClause) 381 { 382 return whereAggregates; 383 } 384 else 385 { 386 return null; 387 } 388 389 default: 390 if (SanityManager.DEBUG) 391 { 392 SanityManager.ASSERT(false, 393 "Unexpected value for clause"); 394 } 395 return null; 396 } 397 } 398 399 404 public SubqueryList getWhereSubquerys() 405 { 406 return whereSubquerys; 407 } 408 409 422 423 public ResultSetNode bindNonVTITables(DataDictionary dataDictionary, 424 FromList fromListParam) 425 throws StandardException 426 { 427 int fromListParamSize = fromListParam.size(); 428 int fromListSize = fromList.size(); 429 int nestingLevel; 430 FromList fromListClone = (FromList) getNodeFactory().getNode( 431 C_NodeTypes.FROM_LIST, 432 getNodeFactory().doJoinOrderOptimization(), 433 getContextManager()); 434 435 wherePredicates = (PredicateList) getNodeFactory().getNode( 436 C_NodeTypes.PREDICATE_LIST, 437 getContextManager()); 438 preJoinFL = (FromList) getNodeFactory().getNode( 439 C_NodeTypes.FROM_LIST, 440 getNodeFactory().doJoinOrderOptimization(), 441 getContextManager()); 442 443 444 if (fromListParam.size() == 0) 445 { 446 nestingLevel = 0; 447 } 448 else 449 { 450 nestingLevel = ((FromTable) fromListParam.elementAt(0)).getLevel() + 1; 451 } 452 fromList.setLevel(nestingLevel); 453 454 457 for (int index = 0; index < fromListSize; index++) 458 { 459 fromListParam.insertElementAt(fromList.elementAt(index), 0); 460 } 461 462 fromList.bindTables(dataDictionary, fromListParam); 464 465 466 for (int index = 0; index < fromListSize; index++) 467 { 468 fromListParam.removeElementAt(0); 469 } 470 return this; 471 } 472 473 482 public void bindExpressions(FromList fromListParam) 483 throws StandardException 484 { 485 int fromListParamSize = fromListParam.size(); 486 int fromListSize = fromList.size(); 487 int numDistinctAggs; 488 489 if (SanityManager.DEBUG) 490 SanityManager.ASSERT(fromList != null && resultColumns != null, 491 "Both fromList and resultColumns are expected to be non-null"); 492 493 497 if (! bindTargetListOnly) 498 { 499 500 fromList.bindExpressions( fromListParam ); 501 } 502 503 selectSubquerys = (SubqueryList) getNodeFactory().getNode( 504 C_NodeTypes.SUBQUERY_LIST, 505 getContextManager()); 506 selectAggregates = new Vector (); 507 508 511 for (int index = 0; index < fromListSize; index++) 512 { 513 fromListParam.insertElementAt(fromList.elementAt(index), index); 514 } 515 516 resultColumns.setClause(ValueNode.IN_SELECT_LIST); 517 resultColumns.bindExpressions(fromListParam, 518 selectSubquerys, 519 selectAggregates); 520 521 524 if (bindTargetListOnly) 525 { 526 for (int index = 0; index < fromListSize; index++) 527 { 528 fromListParam.removeElementAt(0); 529 } 530 return; 531 } 532 533 whereAggregates = new Vector (); 534 whereSubquerys = (SubqueryList) getNodeFactory().getNode( 535 C_NodeTypes.SUBQUERY_LIST, 536 getContextManager()); 537 if (whereClause != null) 538 { 539 getCompilerContext().pushCurrentPrivType( Authorizer.SELECT_PRIV); 540 whereClause = whereClause.bindExpression(fromListParam, 541 whereSubquerys, 542 whereAggregates); 543 544 553 if ((whereAggregates.size() > 0) && 554 !generatedForHavingClause) 555 { 556 throw StandardException.newException(SQLState.LANG_NO_AGGREGATES_IN_WHERE_CLAUSE); 557 } 558 559 561 if (whereClause.isParameterNode()) 562 throw StandardException.newException(SQLState.LANG_NON_BOOLEAN_WHERE_CLAUSE, "PARAMETER" ); 563 if ((whereClause instanceof UnaryOperatorNode) && 564 ((UnaryOperatorNode)whereClause).isUnaryMinusOrPlusWithParameter()) 565 throw StandardException.newException(SQLState.LANG_NON_BOOLEAN_WHERE_CLAUSE, "PARAMETER" ); 566 567 whereClause = whereClause.checkIsBoolean(); 568 getCompilerContext().popCurrentPrivType(); 569 } 570 571 572 for (int index = 0; index < fromListSize; index++) 573 { 574 fromListParam.removeElementAt(0); 575 } 576 577 if (SanityManager.DEBUG) { 578 SanityManager.ASSERT(fromListParam.size() == fromListParamSize, 579 "fromListParam.size() = " + fromListParam.size() + 580 ", expected to be restored to " + fromListParamSize); 581 SanityManager.ASSERT(fromList.size() == fromListSize, 582 "fromList.size() = " + fromList.size() + 583 ", expected to be restored to " + fromListSize); 584 } 585 586 587 if (groupByList != null) 588 { 589 Vector gbAggregateVector = new Vector (); 590 591 groupByList.bindGroupByColumns(this, 592 gbAggregateVector); 593 594 599 if (SanityManager.DEBUG) 600 { 601 SanityManager.ASSERT(gbAggregateVector.size() == 0, 602 "Unexpected Aggregate vector generated by Group By clause"); 603 } 604 } 605 614 if (groupByList != null || selectAggregates.size() > 0) 615 { 616 617 VerifyAggregateExpressionsVisitor visitor = 618 new VerifyAggregateExpressionsVisitor(groupByList); 619 resultColumns.accept(visitor); 620 } 621 622 626 numDistinctAggs = numDistinctAggregates(selectAggregates); 627 if (numDistinctAggs > 1) 628 { 629 throw StandardException.newException(SQLState.LANG_USER_AGGREGATE_MULTIPLE_DISTINCTS); 630 } 631 } 632 633 642 public void bindExpressionsWithTables(FromList fromListParam) 643 throws StandardException 644 { 645 646 bindExpressions(fromListParam); 647 } 648 649 658 659 public void bindTargetExpressions(FromList fromListParam) 660 throws StandardException 661 { 662 bindTargetListOnly = true; 663 bindExpressions(fromListParam); 664 bindTargetListOnly = false; 665 } 666 667 677 678 public void bindResultColumns(FromList fromListParam) 679 throws StandardException 680 { 681 687 fromList.bindResultColumns(fromListParam); 688 super.bindResultColumns(fromListParam); 689 690 691 if (resultColumns.size() > Limits.DB2_MAX_ELEMENTS_IN_SELECT_LIST) 692 { 693 throw StandardException.newException(SQLState.LANG_TOO_MANY_ELEMENTS); 694 } 695 696 697 if (fromList.hasOuterJoins()) 698 resultColumns.setNullability(true); 699 } 700 701 727 728 public void bindResultColumns(TableDescriptor targetTableDescriptor, 729 FromVTI targetVTI, 730 ResultColumnList targetColumnList, 731 DMLStatementNode statement, 732 FromList fromListParam) 733 throws StandardException 734 { 735 741 fromList.bindResultColumns(fromListParam); 742 super.bindResultColumns(targetTableDescriptor, 743 targetVTI, 744 targetColumnList, statement, 745 fromListParam); 746 } 747 748 758 void pushExpressionsIntoSelect(Predicate predicate) 759 throws StandardException 760 { 761 wherePredicates.pullExpressions(referencedTableMap.size(), predicate.getAndNode()); 762 fromList.pushPredicates(wherePredicates); 763 } 764 765 766 774 public void verifySelectStarSubquery(FromList outerFromList, int subqueryType) 775 throws StandardException 776 { 777 if (! ((ResultColumn) resultColumns.elementAt(0) instanceof AllResultColumn) ) 778 { 779 return; 780 } 781 782 785 if (generatedForGroupByClause || generatedForHavingClause) 786 { 787 return; 788 } 789 790 793 if (subqueryType != SubqueryNode.EXISTS_SUBQUERY) 794 { 795 throw StandardException.newException(SQLState.LANG_CANT_SELECT_STAR_SUBQUERY); 796 } 797 798 802 String fullTableName; 803 804 fullTableName = ((AllResultColumn) resultColumns.elementAt(0)).getFullTableName(); 805 806 if (fullTableName != null) 807 { 808 if (fromList.getFromTableByName(fullTableName, null, true) == null && 809 outerFromList.getFromTableByName(fullTableName, null, true) == null) 810 { 811 if (fromList.getFromTableByName(fullTableName, null, false) == null && 812 outerFromList.getFromTableByName(fullTableName, null, false) == null) 813 { 814 throw StandardException.newException(SQLState.LANG_EXPOSED_NAME_NOT_FOUND, fullTableName); 815 } 816 } 817 } 818 } 819 820 833 protected FromTable getFromTableByName(String name, String schemaName, boolean exactMatch) 834 throws StandardException 835 { 836 return fromList.getFromTableByName(name, schemaName, exactMatch); 837 } 838 839 846 847 public void rejectParameters() throws StandardException 848 { 849 super.rejectParameters(); 850 fromList.rejectParameters(); 851 } 852 853 861 void pushOrderByList(OrderByList orderByList) 862 { 863 this.orderByList = orderByList; 864 orderByQuery = true; 866 } 867 868 892 893 public ResultSetNode preprocess(int numTables, 894 GroupByList gbl, 895 FromList fl) 896 throws StandardException 897 { 898 ResultSetNode newTop = this; 899 900 905 normExpressions(); 906 907 913 boolean anyChange = fromList.LOJ_reorderable(numTables); 914 if (anyChange) 915 { 916 FromList afromList = (FromList) getNodeFactory().getNode(C_NodeTypes.FROM_LIST, 917 getNodeFactory().doJoinOrderOptimization(), 918 getContextManager()); 919 bindExpressions(afromList); 920 } 921 922 927 fromList.preprocess(numTables, groupByList, whereClause); 928 929 930 if (SanityManager.DEBUG) 931 { 932 SanityManager.ASSERT(selectSubquerys != null, 933 "selectSubquerys is expected to be non-null"); 934 } 935 936 940 resultColumns.preprocess(numTables, 941 fromList, whereSubquerys, 942 wherePredicates); 943 944 952 if (whereClause != null) 953 { 954 whereClause.preprocess(numTables, 955 fromList, whereSubquerys, 956 wherePredicates); 957 } 958 959 963 if (groupByList != null) 964 { 965 groupByList.preprocess(numTables, fromList, whereSubquerys, wherePredicates); 966 } 967 968 969 if (whereClause != null) 970 { 971 wherePredicates.pullExpressions(numTables, whereClause); 972 whereClause = null; 973 } 974 975 978 979 fromList.flattenFromTables(resultColumns, 981 wherePredicates, 982 whereSubquerys, 983 groupByList); 984 985 if (wherePredicates != null && wherePredicates.size() > 0 && fromList.size() > 0) 986 { 987 if (fromList.size() > 1) 989 { 990 performTransitiveClosure(numTables); 991 } 992 993 if (orderByList != null) 994 { 995 orderByList.removeConstantColumns(wherePredicates); 999 1000 1005 if (orderByList.size() == 0) 1006 { 1007 orderByList = null; 1008 } 1009 } 1010 } 1011 1012 1016 if (groupByList != null && 1017 selectAggregates.size() == 0 && 1018 whereAggregates.size() == 0) 1019 { 1020 isDistinct = true; 1021 groupByList = null; 1022 } 1023 1024 1045 if (isDistinct && groupByList == null) 1046 { 1047 int distinctTable = resultColumns.allTopCRsFromSameTable(); 1048 1049 if (distinctTable != -1) 1050 { 1051 if (fromList.returnsAtMostSingleRow(resultColumns, 1052 whereClause, wherePredicates, 1053 getDataDictionary())) 1054 { 1055 isDistinct = false; 1056 } 1057 } 1058 1059 1074 if (isDistinct && orderByList != null && orderByList.allAscending()) 1075 { 1076 1079 if (orderByList.isInOrderPrefix(resultColumns)) 1080 { 1081 orderByList = null; 1082 } 1083 else 1084 { 1085 1090 newTop = genProjectRestrictForReordering(); 1091 orderByList.resetToSourceRCs(); 1092 resultColumns = orderByList.reorderRCL(resultColumns); 1093 orderByList = null; 1094 } 1095 orderByAndDistinctMerged = true; 1096 } 1097 } 1098 1099 1109 fromList.pushPredicates(wherePredicates); 1110 1111 1112 referencedTableMap = new JBitSet(numTables); 1113 int flSize = fromList.size(); 1114 for (int index = 0; index < flSize; index++) 1115 { 1116 referencedTableMap.or(((FromTable) fromList.elementAt(index)). 1117 getReferencedTableMap()); 1118 } 1119 1120 1121 if (newTop != this) 1122 { 1123 newTop.setReferencedTableMap((JBitSet) referencedTableMap.clone()); 1124 } 1125 return newTop; 1126 } 1127 1128 1137 private void performTransitiveClosure(int numTables) 1138 throws StandardException 1139 { 1140 wherePredicates.joinClauseTransitiveClosure(numTables, fromList, getCompilerContext()); 1142 1143 wherePredicates.searchClauseTransitiveClosure(numTables, fromList.hashJoinSpecified()); 1145 } 1146 1147 1151 private void normExpressions() 1152 throws StandardException 1153 { 1154 1160 if (whereClause != null) 1161 { 1162 whereClause = whereClause.eliminateNots(false); 1163 if (SanityManager.DEBUG) 1164 { 1165 if (!(whereClause.verifyEliminateNots()) ) 1166 { 1167 whereClause.treePrint(); 1168 SanityManager.THROWASSERT( 1169 "whereClause in invalid form: " + whereClause); 1170 } 1171 } 1172 whereClause = whereClause.putAndsOnTop(); 1173 if (SanityManager.DEBUG) 1174 { 1175 if (! ((whereClause instanceof AndNode) && 1176 (whereClause.verifyPutAndsOnTop())) ) 1177 { 1178 whereClause.treePrint(); 1179 SanityManager.THROWASSERT( 1180 "whereClause in invalid form: " + whereClause); 1181 } 1182 } 1183 whereClause = whereClause.changeToCNF(true); 1184 if (SanityManager.DEBUG) 1185 { 1186 if (! ((whereClause instanceof AndNode) && 1187 (whereClause.verifyChangeToCNF())) ) 1188 { 1189 whereClause.treePrint(); 1190 SanityManager.THROWASSERT( 1191 "whereClause in invalid form: " + whereClause); 1192 } 1193 } 1194 } 1195 } 1196 1197 1208 public ResultSetNode addNewPredicate(Predicate predicate) 1209 throws StandardException 1210 { 1211 wherePredicates.addPredicate(predicate); 1212 return this; 1213 } 1214 1215 1229 public boolean flattenableInFromSubquery(FromList fromList) 1230 { 1231 if (isDistinct) 1232 { 1233 return false; 1234 } 1235 if (this.fromList.size() > 1) 1236 { 1237 return false; 1238 } 1239 1240 1241 if ((selectSubquerys != null) && 1242 (selectSubquerys.size() > 0)) 1243 { 1244 return false; 1245 } 1246 1247 1248 if ((groupByList != null) || generatedForHavingClause) 1249 { 1250 return false; 1251 } 1252 1253 1255 if (! resultColumns.isCloneable()) 1256 { 1257 return false; 1258 } 1259 1260 1261 if ((selectAggregates != null) && 1262 (selectAggregates.size() > 0)) 1263 { 1264 return false; 1265 } 1266 1267 return true; 1268 } 1269 1270 1280 1281 public ResultSetNode genProjectRestrict(int origFromListSize) 1282 throws StandardException 1283 { 1284 boolean orderingDependent = false; 1285 PredicateList restrictionList; 1286 ResultColumnList prRCList; 1287 ResultSetNode prnRSN; 1288 1289 1290 prnRSN = (ResultSetNode) getNodeFactory().getNode( 1291 C_NodeTypes.PROJECT_RESTRICT_NODE, 1292 fromList.elementAt(0), 1293 resultColumns, 1294 whereClause, 1295 wherePredicates, 1296 selectSubquerys, 1297 whereSubquerys, 1298 null, 1299 getContextManager() ); 1300 1301 1309 if (((selectAggregates != null) && (selectAggregates.size() > 0)) 1310 || (groupByList != null)) 1311 { 1312 GroupByNode gbn = (GroupByNode) getNodeFactory().getNode( 1313 C_NodeTypes.GROUP_BY_NODE, 1314 prnRSN, 1315 groupByList, 1316 selectAggregates, 1317 null, 1318 getContextManager()); 1319 gbn.considerPostOptimizeOptimizations(originalWhereClause != null); 1320 gbn.assignCostEstimate(optimizer.getOptimizedCost()); 1321 1322 groupByList = null; 1323 prnRSN = gbn.getParent(); 1324 1325 orderingDependent = orderingDependent || gbn.getIsInSortedOrder(); 1327 } 1328 1329 if (isDistinct) 1331 { 1332 resultColumns.verifyAllOrderable(); 1335 1336 1358 boolean distinctScanPossible = false; 1359 if (origFromListSize == 1 && 1360 (! orderByAndDistinctMerged) && 1361 resultColumns.countNumberOfSimpleColumnReferences() == resultColumns.size()) 1362 { 1363 boolean simpleColumns = true; 1364 HashSet distinctColumns = new HashSet (); 1365 int size = resultColumns.size(); 1366 for (int i = 1; i <= size; i++) { 1367 BaseColumnNode bc = resultColumns.getResultColumn(i).getBaseColumnNode(); 1368 if (bc == null) { 1369 simpleColumns = false; 1370 break; 1371 } 1372 distinctColumns.add(bc); 1373 } 1374 if (simpleColumns && prnRSN.isPossibleDistinctScan(distinctColumns)) { 1375 prnRSN.markForDistinctScan(); 1376 distinctScanPossible = true; 1377 } 1378 } 1379 1380 if (!distinctScanPossible) 1381 { 1382 1385 boolean inSortedOrder = isOrderedResult(resultColumns, prnRSN, !(orderByAndDistinctMerged)); 1386 prnRSN = (ResultSetNode) getNodeFactory().getNode( 1387 C_NodeTypes.DISTINCT_NODE, 1388 prnRSN, 1389 new Boolean (inSortedOrder), 1390 null, 1391 getContextManager()); 1392 prnRSN.costEstimate = costEstimate.cloneMe(); 1393 1394 orderingDependent = orderingDependent || inSortedOrder; 1396 } 1397 } 1398 1399 1402 if (orderByList != null) 1403 { 1404 if (orderByList.getSortNeeded()) 1405 { 1406 prnRSN = (ResultSetNode) getNodeFactory().getNode( 1407 C_NodeTypes.ORDER_BY_NODE, 1408 prnRSN, 1409 orderByList, 1410 null, 1411 getContextManager()); 1412 prnRSN.costEstimate = costEstimate.cloneMe(); 1413 } 1414 1415 int orderBySelect = this.getResultColumns().getOrderBySelect(); 1416 if (orderBySelect > 0) 1417 { 1418 ResultColumnList selectRCs = prnRSN.getResultColumns().copyListAndObjects(); 1419 int wholeSize = selectRCs.size(); 1420 for (int i = wholeSize - 1; orderBySelect > 0; i--, orderBySelect--) 1421 selectRCs.removeElementAt(i); 1422 selectRCs.genVirtualColumnNodes(prnRSN, prnRSN.getResultColumns()); 1423 prnRSN = (ResultSetNode) getNodeFactory().getNode( 1424 C_NodeTypes.PROJECT_RESTRICT_NODE, 1425 prnRSN, 1426 selectRCs, 1427 null, 1428 null, 1429 null, 1430 null, 1431 null, 1432 getContextManager()); 1433 } 1434 } 1435 1436 if (!(orderByList != null && orderByList.getSortNeeded()) && orderByQuery) 1437 { 1438 orderingDependent = true; 1440 } 1441 1442 1447 if (orderingDependent) 1448 { 1449 prnRSN.markOrderingDependent(); 1450 } 1451 1452 1453 prnRSN.costEstimate = costEstimate.cloneMe(); 1454 1455 return prnRSN; 1456 } 1457 1458 1474 private boolean isOrderedResult(ResultColumnList resultColumns, 1475 ResultSetNode newTopRSN, 1476 boolean permuteOrdering) 1477 throws StandardException 1478 { 1479 int rclSize = resultColumns.size(); 1480 1481 1484 int numCRs = 0; 1485 for (int index = 0; index < rclSize; index++) 1486 { 1487 ResultColumn rc = (ResultColumn) resultColumns.elementAt(index); 1488 if (rc.getExpression() instanceof ColumnReference) 1489 { 1490 numCRs++; 1491 } 1492 else if (! (rc.getExpression() instanceof ConstantNode)) 1493 { 1494 return false; 1495 } 1496 } 1497 1498 if (numCRs == 0) 1500 { 1501 return true; 1502 } 1503 1504 ColumnReference[] crs = new ColumnReference[numCRs]; 1505 1506 int crsIndex = 0; 1508 for (int index = 0; index < rclSize; index++) 1509 { 1510 ResultColumn rc = (ResultColumn) resultColumns.elementAt(index); 1511 if (rc.getExpression() instanceof ColumnReference) 1512 { 1513 crs[crsIndex++] = (ColumnReference) rc.getExpression(); 1514 } 1515 } 1516 1517 return newTopRSN.isOrderedOn(crs, permuteOrdering, (Vector )null); 1518 } 1519 1520 1528 public ResultSetNode ensurePredicateList(int numTables) 1529 throws StandardException 1530 { 1531 return this; 1532 } 1533 1534 1546 1547 public ResultSetNode optimize(DataDictionary dataDictionary, 1548 PredicateList predicateList, 1549 double outerRows) 1550 throws StandardException 1551 { 1552 Optimizer optimizer; 1553 1554 1555 1556 1557 if (SanityManager.DEBUG) 1558 SanityManager.ASSERT(selectSubquerys != null, 1559 "selectSubquerys is expected to be non-null"); 1560 1561 1572 1573 if (wherePredicates != null) 1574 { 1575 for (int i = wherePredicates.size() - 1; i >= 0; i--) 1577 { 1578 if (((Predicate)wherePredicates.elementAt(i)).isScopedForPush()) 1579 wherePredicates.removeOptPredicate(i); 1580 } 1581 } 1582 1583 1584 1585 1610 if (predicateList != null) 1611 { 1612 if (wherePredicates == null) { 1613 wherePredicates = (PredicateList) getNodeFactory().getNode( 1614 C_NodeTypes.PREDICATE_LIST, 1615 getContextManager()); 1616 } 1617 1618 Predicate pred = null; 1619 int sz = predicateList.size(); 1620 for (int i = sz - 1; i >= 0; i--) 1621 { 1622 pred = (Predicate)predicateList.getOptPredicate(i); 1626 if (pred.isScopedToSourceResultSet()) 1627 { 1628 wherePredicates.addOptPredicate(pred); 1633 predicateList.removeOptPredicate(pred); 1634 } 1635 } 1636 } 1637 1638 optimizer = getOptimizer(fromList, 1639 wherePredicates, 1640 dataDictionary, 1641 orderByList); 1642 optimizer.setOuterRows(outerRows); 1643 1644 1645 while (optimizer.getNextPermutation()) 1646 { 1647 while (optimizer.getNextDecoratedPermutation()) 1648 { 1649 optimizer.costPermutation(); 1650 } 1651 } 1652 1653 1659 if (wherePredicates != null) 1660 { 1661 Predicate pred = null; 1662 for (int i = wherePredicates.size() - 1; i >= 0; i--) 1663 { 1664 pred = (Predicate)wherePredicates.getOptPredicate(i); 1665 if (pred.isScopedForPush()) 1666 { 1667 predicateList.addOptPredicate(pred); 1668 wherePredicates.removeOptPredicate(pred); 1669 } 1670 } 1671 } 1672 1673 1674 costEstimate = optimizer.getOptimizedCost(); 1675 1676 1677 if ((selectAggregates != null) && (selectAggregates.size() > 0)) 1678 { 1679 costEstimate.setEstimatedRowCount((long) outerRows); 1680 costEstimate.setSingleScanRowCount(1); 1681 } 1682 1683 selectSubquerys.optimize(dataDictionary, costEstimate.rowCount()); 1684 1685 if (whereSubquerys != null && whereSubquerys.size() > 0) 1686 { 1687 whereSubquerys.optimize(dataDictionary, costEstimate.rowCount()); 1688 } 1689 1690 return this; 1691 } 1692 1693 1703 public ResultSetNode modifyAccessPaths(PredicateList predList) 1704 throws StandardException 1705 { 1706 1712 if (SanityManager.DEBUG) 1713 { 1714 SanityManager.ASSERT(optimizer != null, 1715 "SelectNode's optimizer not expected to be null when " + 1716 "modifying access paths."); 1717 } 1718 1719 ((OptimizerImpl)optimizer).addScopedPredicatesToList(predList); 1720 return modifyAccessPaths(); 1721 } 1722 1723 1730 public ResultSetNode modifyAccessPaths() throws StandardException 1731 { 1732 int origFromListSize = fromList.size(); 1733 ResultColumnList leftRCList; 1734 ResultColumnList rightRCList; 1735 ResultSetNode leftResultSet; 1736 ResultSetNode rightResultSet; 1737 1738 1743 optimizer.modifyAccessPaths(); 1744 1745 costEstimate = optimizer.getFinalCost(); 1747 1748 if (SanityManager.DEBUG) 1749 { 1750 if (wherePredicates != null) 1760 { 1761 Predicate pred = null; 1762 for (int i = wherePredicates.size() - 1; i >= 0; i--) 1763 { 1764 pred = (Predicate)wherePredicates.getOptPredicate(i); 1765 if (pred.isScopedForPush()) 1766 { 1767 SanityManager.THROWASSERT("Found scoped predicate " + 1768 pred.binaryRelOpColRefsToString() + 1769 " in WHERE list when no scoped predicates were" + 1770 " expected."); 1771 } 1772 } 1773 } 1774 } 1775 1776 selectSubquerys.modifyAccessPaths(); 1777 1778 if (whereSubquerys != null && whereSubquerys.size() > 0) 1779 { 1780 whereSubquerys.modifyAccessPaths(); 1781 } 1782 1783 1784 preJoinFL.removeAllElements(); 1785 preJoinFL.nondestructiveAppend(fromList); 1786 1787 1801 while (fromList.size() > 1) 1802 { 1803 1807 leftResultSet = (ResultSetNode) fromList.elementAt(0); 1808 leftRCList = leftResultSet.getResultColumns(); 1809 leftResultSet.setResultColumns(leftRCList.copyListAndObjects()); 1810 leftRCList.genVirtualColumnNodes(leftResultSet, leftResultSet.resultColumns); 1811 1812 1817 rightResultSet = (ResultSetNode) fromList.elementAt(1); 1818 rightRCList = rightResultSet.getResultColumns(); 1819 rightResultSet.setResultColumns(rightRCList.copyListAndObjects()); 1820 rightRCList.genVirtualColumnNodes(rightResultSet, rightResultSet.resultColumns); 1821 rightRCList.adjustVirtualColumnIds(leftRCList.size()); 1822 1823 1824 leftRCList.nondestructiveAppend(rightRCList); 1825 1826 1829 fromList.setElementAt( 1830 (JoinNode) getNodeFactory().getNode( 1831 C_NodeTypes.JOIN_NODE, 1832 leftResultSet, 1833 rightResultSet, 1834 null, 1835 null, 1836 leftRCList, 1837 null, 1838 fromList.properties, 1840 getContextManager() 1841 ), 1842 0 1843 ); 1844 1845 fromList.removeElementAt(1); 1846 } 1847 1848 return genProjectRestrict(origFromListSize); 1849 } 1850 1851 1858 public CostEstimate getFinalCostEstimate() 1859 throws StandardException 1860 { 1861 return optimizer.getFinalCost(); 1862 } 1863 1864 1867 boolean isUpdatableCursor(DataDictionary dd) throws StandardException 1868 { 1869 TableDescriptor targetTableDescriptor; 1870 1871 if (isDistinct) 1872 { 1873 if (SanityManager.DEBUG) 1874 SanityManager.DEBUG("DumpUpdateCheck","cursor select has distinct"); 1875 return false; 1876 } 1877 1878 if ((selectAggregates == null) || (selectAggregates.size() > 0)) 1879 { 1880 return false; 1881 } 1882 1883 if (groupByList != null || generatedForHavingClause) 1884 { 1885 return false; 1886 } 1887 1888 if (SanityManager.DEBUG) 1889 SanityManager.ASSERT(fromList!=null, "select must have from tables"); 1890 if (fromList.size() != 1) 1891 { 1892 if (SanityManager.DEBUG) 1893 SanityManager.DEBUG("DumpUpdateCheck","cursor select has more than one from table"); 1894 return false; 1895 } 1896 1897 targetTable = (FromTable)(fromList.elementAt(0)); 1898 1899 if (targetTable instanceof FromVTI) { 1900 1901 return ((FromVTI) targetTable).isUpdatableCursor(); 1902 } 1903 1904 if (! (targetTable instanceof FromBaseTable)) 1905 { 1906 if (SanityManager.DEBUG) 1907 SanityManager.DEBUG("DumpUpdateCheck","cursor select has non base table as target table"); 1908 return false; 1909 } 1910 1911 1912 1921 targetTableDescriptor = getTableDescriptor( 1922 ((FromBaseTable)targetTable).getBaseTableName(), 1923 getSchemaDescriptor(((FromBaseTable)targetTable).getTableNameField().getSchemaName())); 1924 if (targetTableDescriptor.getTableType() == TableDescriptor.SYSTEM_TABLE_TYPE) 1925 { 1926 if (SanityManager.DEBUG) 1927 SanityManager.DEBUG("DumpUpdateCheck","cursor select is on system table"); 1928 return false; 1929 } 1930 if (targetTableDescriptor.getTableType() == TableDescriptor.VIEW_TYPE) 1931 { 1932 if (SanityManager.DEBUG) 1933 SanityManager.DEBUG("DumpUpdateCheck","cursor select is on view"); 1934 return false; 1935 } 1936 if ((getSelectSubquerys() != null) && 1937 (getSelectSubquerys().size() != 0)) 1938 { 1939 if (SanityManager.DEBUG) 1940 SanityManager.DEBUG("DumpUpdateCheck","cursor select has subquery in SELECT list"); 1941 return false; 1942 } 1943 1944 if ((getWhereSubquerys() != null) && 1945 (getWhereSubquerys().size() != 0)) 1946 { 1947 if (SanityManager.DEBUG) 1948 SanityManager.DEBUG("DumpUpdateCheck","cursor select has subquery in WHERE clause"); 1949 return false; 1950 } 1951 1952 return true; 1953 } 1954 1955 1959 FromTable getCursorTargetTable() 1960 { 1961 if (SanityManager.DEBUG) 1962 SanityManager.ASSERT(targetTable!=null, 1963 "must call isUpdatableCursor() first, and must be updatable"); 1964 return targetTable; 1965 } 1966 1967 1977 public boolean referencesTarget(String name, boolean baseTable) 1978 throws StandardException 1979 { 1980 if (fromList.referencesTarget(name, baseTable) || 1981 (selectSubquerys != null && selectSubquerys.referencesTarget(name, baseTable)) || 1982 (whereSubquerys != null && whereSubquerys.referencesTarget(name, baseTable)) 1983 ) 1984 { 1985 return true; 1986 } 1987 return false; 1988 } 1989 1990 1993 public void disablePrivilegeCollection() 1994 { 1995 super.disablePrivilegeCollection(); 1996 int fromListSize = fromList.size(); 1997 for( int i = 0; i < fromListSize; i++) 1998 ((FromTable) fromList.elementAt(i)).disablePrivilegeCollection(); 1999 } 2000 2001 2012 boolean subqueryReferencesTarget(String name, boolean baseTable) 2013 throws StandardException 2014 { 2015 if ((selectSubquerys != null && selectSubquerys.referencesTarget(name, baseTable)) || 2016 (whereSubquerys != null && whereSubquerys.referencesTarget(name, baseTable)) 2017 ) 2018 { 2019 return true; 2020 } 2021 return false; 2022 } 2023 2024 2031 public void bindUntypedNullsToResultColumns(ResultColumnList bindingRCL) 2032 throws StandardException 2033 { 2034 fromList.bindUntypedNullsToResultColumns(bindingRCL); 2035 } 2036 2037 2044 void decrementLevel(int decrement) 2045 { 2046 2047 fromList.decrementLevel(decrement); 2048 selectSubquerys.decrementLevel(decrement); 2049 whereSubquerys.decrementLevel(decrement); 2050 2053 wherePredicates.decrementLevel(fromList, decrement); 2054 } 2055 2056 2077 boolean uniqueSubquery(boolean additionalEQ) 2078 throws StandardException 2079 { 2080 ColumnReference additionalCR = null; 2081 ResultColumn rc = (ResultColumn) getResultColumns().elementAt(0); 2082 2083 2086 if (additionalEQ && 2087 rc.getExpression() instanceof ColumnReference) 2088 { 2089 additionalCR = (ColumnReference) rc.getExpression(); 2090 2091 2094 if (additionalCR.getCorrelated()) 2095 { 2096 additionalCR = null; 2097 } 2098 } 2099 2100 return fromList.returnsAtMostSingleRow((additionalCR == null) ? null : getResultColumns(), 2101 whereClause, wherePredicates, 2102 getDataDictionary()); 2103 } 2104 2105 2114 public int updateTargetLockMode() 2115 { 2116 2117 return fromList.updateTargetLockMode(); 2118 } 2119 2120 2128 boolean returnsAtMostOneRow() 2129 { 2130 return (groupByList == null && selectAggregates != null && selectAggregates.size() != 0); 2131 } 2132 2133 2140 public boolean referencesSessionSchema() 2141 throws StandardException 2142 { 2143 if (fromList.referencesSessionSchema() || 2144 (selectSubquerys != null && selectSubquerys.referencesSessionSchema()) || 2145 (whereSubquerys != null && whereSubquerys.referencesSessionSchema())) 2146 return true; 2147 2148 return false; 2149 } 2150 2151 2159 public Visitable accept(Visitor v) 2160 throws StandardException 2161 { 2162 Visitable returnNode = v.visit(this); 2163 2164 if (v.skipChildren(this)) 2165 { 2166 return returnNode; 2167 } 2168 2169 if (!v.stopTraversal()) 2170 { 2171 super.accept(v); 2172 } 2173 2174 if (fromList != null && !v.stopTraversal()) 2175 { 2176 fromList = (FromList)fromList.accept(v); 2177 } 2178 2179 if (whereClause != null && !v.stopTraversal()) 2180 { 2181 whereClause = (ValueNode)whereClause.accept(v); 2182 } 2183 2184 if (wherePredicates != null && !v.stopTraversal()) 2185 { 2186 wherePredicates = (PredicateList)wherePredicates.accept(v); 2187 } 2188 2189 return returnNode; 2190 } 2191} 2192 | Popular Tags |