1 21 22 package org.apache.derby.impl.sql.compile; 23 24 import org.apache.derby.iapi.services.loader.ClassInspector; 25 import org.apache.derby.iapi.services.loader.GeneratedMethod; 26 27 import org.apache.derby.iapi.services.context.ContextManager; 28 29 import org.apache.derby.iapi.services.compiler.MethodBuilder; 30 import org.apache.derby.iapi.services.compiler.LocalField; 31 32 import org.apache.derby.iapi.services.sanity.SanityManager; 33 34 import org.apache.derby.iapi.error.StandardException; 35 36 import org.apache.derby.iapi.sql.compile.CompilerContext; 37 import org.apache.derby.iapi.sql.compile.OptimizablePredicateList; 38 import org.apache.derby.iapi.sql.compile.Optimizer; 39 import org.apache.derby.iapi.sql.compile.OptimizablePredicate; 40 import org.apache.derby.iapi.sql.compile.Optimizable; 41 import org.apache.derby.iapi.sql.compile.CostEstimate; 42 import org.apache.derby.iapi.sql.compile.Visitable; 43 import org.apache.derby.iapi.sql.compile.Visitor; 44 import org.apache.derby.iapi.sql.compile.RowOrdering; 45 import org.apache.derby.iapi.sql.compile.C_NodeTypes; 46 47 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext; 48 49 import org.apache.derby.iapi.sql.dictionary.DataDictionary; 50 import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor; 51 import org.apache.derby.iapi.sql.dictionary.ColumnDescriptorList; 52 import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor; 53 import org.apache.derby.iapi.sql.dictionary.TableDescriptor; 54 55 import org.apache.derby.iapi.reference.ClassName; 56 import org.apache.derby.iapi.reference.JDBC20Translation; 57 import org.apache.derby.iapi.reference.SQLState; 58 59 import org.apache.derby.iapi.sql.Activation; 60 61 import org.apache.derby.catalog.UUID; 62 63 import org.apache.derby.vti.DeferModification; 64 import org.apache.derby.vti.VTICosting; 65 import org.apache.derby.vti.VTIEnvironment; 66 67 import org.apache.derby.iapi.util.JBitSet; 68 import org.apache.derby.iapi.services.io.FormatableBitSet; 69 import org.apache.derby.iapi.services.classfile.VMOpcode; 70 import org.apache.derby.iapi.services.info.JVMInfo; 71 72 import org.apache.derby.impl.sql.compile.ActivationClassBuilder; 73 import org.apache.derby.iapi.sql.execute.ExecutionContext; 74 75 import java.lang.reflect.Constructor ; 76 import java.lang.reflect.InvocationTargetException ; 77 78 import java.sql.PreparedStatement ; 79 import java.sql.ResultSet ; 80 import java.sql.ResultSetMetaData ; 81 import java.sql.SQLException ; 82 import java.sql.Types ; 83 84 import java.util.Enumeration ; 85 import java.util.Properties ; 86 import java.util.Vector ; 87 import org.apache.derby.iapi.services.io.FormatableHashtable; 88 89 import java.lang.reflect.Modifier ; 90 91 96 public class FromVTI extends FromTable implements VTIEnvironment 97 { 98 99 JBitSet correlationMap; 100 JBitSet dependencyMap; 101 NewInvocationNode newInvocation; 102 TableName exposedName; 103 SubqueryList subqueryList; 104 boolean implementsVTICosting; 105 boolean optimized; 106 boolean materializable; 107 boolean isTarget; 108 ResultSet rs; 109 110 private FormatableHashtable compileTimeConstants; 111 112 protected int numVTICols; 114 115 private PredicateList restrictionList; 116 117 118 121 private boolean forUpdatePresent; 122 123 124 127 private boolean emptyForUpdate; 128 129 130 134 double estimatedCost = VTICosting.defaultEstimatedCost; 135 double estimatedRowCount = VTICosting.defaultEstimatedRowCount; 136 boolean supportsMultipleInstantiations = true; 137 boolean vtiCosted; 138 139 140 protected boolean version2; 141 private boolean implementsPushable; 142 private PreparedStatement ps; 143 144 private JavaValueNode[] methodParms; 145 146 private boolean controlsDeferral; 147 private boolean isInsensitive; 148 private int resultSetType = ResultSet.TYPE_FORWARD_ONLY; 149 150 158 public void init( 159 Object newInvocation, 160 Object correlationName, 161 Object derivedRCL, 162 Object tableProperties) 163 throws StandardException 164 { 165 init( newInvocation, 166 correlationName, 167 derivedRCL, 168 tableProperties, 169 makeTableName(null, (String ) correlationName)); 170 } 171 172 181 public void init( 182 Object newInvocation, 183 Object correlationName, 184 Object derivedRCL, 185 Object tableProperties, 186 Object exposedTableName) 187 throws StandardException 188 { 189 super.init(correlationName, tableProperties); 190 this.newInvocation = (NewInvocationNode) newInvocation; 191 resultColumns = (ResultColumnList) derivedRCL; 192 subqueryList = (SubqueryList) getNodeFactory().getNode( 193 C_NodeTypes.SUBQUERY_LIST, 194 getContextManager()); 195 196 200 this.exposedName = (TableName) exposedTableName; 201 } 202 203 205 210 public CostEstimate estimateCost( 211 OptimizablePredicateList predList, 212 ConglomerateDescriptor cd, 213 CostEstimate outerCost, 214 Optimizer optimizer, 215 RowOrdering rowOrdering) 216 throws StandardException 217 { 218 costEstimate = getCostEstimate(optimizer); 219 220 224 if (implementsVTICosting && ! vtiCosted) 225 { 226 try 227 { 228 VTICosting vtic = (version2) ? (VTICosting) ps : (VTICosting) rs; 229 estimatedCost = vtic.getEstimatedCostPerInstantiation(this); 230 estimatedRowCount = vtic.getEstimatedRowCount(this); 231 supportsMultipleInstantiations = vtic.supportsMultipleInstantiations(this); 232 233 if (ps != null) { 234 ps.close(); 235 ps = null; 236 } 237 if (rs != null) { 238 rs.close(); 239 rs = null; 240 } 241 } 242 catch (SQLException sqle) 243 { 244 throw StandardException.unexpectedUserException(sqle); 245 } 246 vtiCosted = true; 247 } 248 249 costEstimate.setCost(estimatedCost, estimatedRowCount, estimatedRowCount); 250 251 263 if (getCurrentAccessPath(). 264 getJoinStrategy(). 265 multiplyBaseCostByOuterRows()) 266 { 267 costEstimate.multiply(outerCost.rowCount(), costEstimate); 268 } 269 270 if ( ! optimized) 271 { 272 subqueryList.optimize(optimizer.getDataDictionary(), 273 costEstimate.rowCount()); 274 subqueryList.modifyAccessPaths(); 275 } 276 277 optimized = true; 278 279 return costEstimate; 280 } 281 282 285 public boolean legalJoinOrder(JBitSet assignedTableMap) 286 { 287 292 JBitSet tempBitSet = (JBitSet) assignedTableMap; 293 tempBitSet.or(correlationMap); 294 295 296 return tempBitSet.contains(dependencyMap); 297 } 298 299 300 303 public boolean isMaterializable() 304 { 305 return materializable; 306 } 307 308 309 public boolean supportsMultipleInstantiations() 310 { 311 return supportsMultipleInstantiations; 312 } 313 314 319 public Optimizable modifyAccessPath(JBitSet outerTables) throws StandardException 320 { 321 322 if (rs != null) 323 { 324 try 325 { 326 rs.close(); 327 rs = null; 328 } 329 catch(Throwable t) 330 { 331 throw StandardException.unexpectedUserException(t); 332 } 333 } 334 335 return super.modifyAccessPath(outerTables); 336 } 337 338 public boolean pushOptPredicate(OptimizablePredicate optimizablePredicate) 339 throws StandardException 340 { 341 if (!implementsPushable) 342 return false; 343 344 if( ! optimizablePredicate.getReferencedMap().hasSingleBitSet()) 346 return false; 347 348 if (restrictionList == null) { 349 restrictionList = (PredicateList) getNodeFactory().getNode( 350 C_NodeTypes.PREDICATE_LIST, 351 getContextManager()); 352 } 353 354 restrictionList.addPredicate((Predicate) optimizablePredicate); 355 return true; 356 } 357 358 359 365 366 public String toString() 367 { 368 if (SanityManager.DEBUG) 369 { 370 return "materializable: " + materializable + "\n" + 371 super.toString(); 372 } 373 else 374 { 375 return ""; 376 } 377 } 378 379 385 386 public void printSubNodes(int depth) 387 { 388 if (SanityManager.DEBUG) { 389 super.printSubNodes(depth); 390 391 if (newInvocation != null) 392 { 393 printLabel(depth, "newInvocation: "); 394 newInvocation.treePrint(depth + 1); 395 } 396 397 if (exposedName != null) 398 { 399 printLabel(depth, "exposedName: "); 400 exposedName.treePrint(depth + 1); 401 } 402 403 if (subqueryList != null) 404 { 405 printLabel(depth, "subqueryList: "); 406 subqueryList.treePrint(depth + 1); 407 } 408 } 409 } 410 411 416 public NewInvocationNode getNewInvocation() 417 { 418 return newInvocation; 419 } 420 421 427 428 public String getExposedName() 429 { 430 return correlationName; 431 } 432 433 437 public TableName getExposedTableName() 438 { 439 return exposedName; 440 } 441 442 445 void setTarget() 446 { 447 isTarget = true; 448 version2 = true; 449 } 450 451 462 463 public ResultSetNode bindNonVTITables(DataDictionary dataDictionary, 464 FromList fromListParam) 465 throws StandardException 466 { 467 468 469 if (tableNumber == -1) tableNumber = getCompilerContext().getNextTableNumber(); 471 return this; 472 } 473 474 477 String getVTIName() 478 { 479 return newInvocation.getJavaClassName(); 480 } 482 491 492 public ResultSetNode bindVTITables(FromList fromListParam) 493 throws StandardException 494 { 495 ResultColumnList derivedRCL = resultColumns; 496 497 LanguageConnectionContext lcc = getLanguageConnectionContext(); 498 499 503 504 508 Vector aggregateVector = new Vector (); 509 newInvocation.bindExpression(fromListParam, 510 subqueryList, 511 aggregateVector); 512 513 518 519 if (!newInvocation.assignableTo("java.sql.PreparedStatement")) 520 { 521 if (version2) 522 { 523 throw StandardException.newException(SQLState.LANG_DOES_NOT_IMPLEMENT, 524 getVTIName(), 525 "java.sql.PreparedStatement"); 526 } 527 else if (! newInvocation.assignableTo("java.sql.ResultSet")) 528 { 529 throw StandardException.newException(SQLState.LANG_DOES_NOT_IMPLEMENT, 530 getVTIName(), 531 "java.sql.ResultSet"); 532 } 533 } 534 else 535 { 536 version2 = true; 537 } 538 539 540 if (version2) 541 { 542 implementsPushable = newInvocation.assignableTo("org.apache.derby.vti.IQualifyable"); 544 } 545 546 implementsVTICosting = newInvocation.assignableTo(ClassName.VTICosting); 548 549 550 methodParms = newInvocation.getMethodParms(); 552 553 560 UUID triggerTableId; 561 if ((triggerTableId = getSpecialTriggerVTITableName(lcc, newInvocation.getJavaClassName())) != null) 562 { 563 TableDescriptor td = getDataDictionary().getTableDescriptor(triggerTableId); 564 resultColumns = genResultColList(td); 565 566 vtiCosted = true; 568 estimatedCost = 50d; 569 estimatedRowCount = 5d; 570 supportsMultipleInstantiations = true; 571 } 572 else 573 { 574 ResultSetMetaData rsmd = getResultSetMetaData(); 575 576 579 if (rsmd == null) 580 { 581 throw StandardException.newException(SQLState.LANG_NULL_RESULT_SET_META_DATA, 582 getVTIName()); 583 } 584 585 try 587 { 588 numVTICols = rsmd.getColumnCount(); 589 } 590 catch (SQLException sqle) 591 { 592 numVTICols = 0; 593 } 594 595 try 596 { 597 for( int i = 1; i <= numVTICols; i++) 598 { 599 int columnType = rsmd.getColumnType(i); 600 if( columnType == Types.BLOB || columnType == Types.CLOB) 601 throw StandardException.newException(SQLState.LANG_VTI_BLOB_CLOB_UNSUPPORTED, 602 getVTIName(), rsmd.getColumnName( i)); 603 } 604 } 605 catch( SQLException sqle) 606 { 607 throw StandardException.unexpectedUserException(sqle); 608 } 609 610 resultColumns = (ResultColumnList) getNodeFactory().getNode( 611 C_NodeTypes.RESULT_COLUMN_LIST, 612 getContextManager()); 613 resultColumns.createListFromResultSetMetaData(rsmd, exposedName, 614 newInvocation.getJavaClassName()); 615 } 616 numVTICols = resultColumns.size(); 617 618 619 if (derivedRCL != null) 620 { 621 resultColumns.propagateDCLInfo(derivedRCL, correlationName); 622 } 623 624 return this; 625 } 626 627 637 public ResultSetMetaData getResultSetMetaData() 638 throws StandardException 639 { 640 ResultSetMetaData rsmd = null; 642 643 try 644 { 645 if (version2) 646 { 647 ps = (PreparedStatement ) getNewInstance(); 648 649 if (ps.getResultSetConcurrency() != JDBC20Translation.CONCUR_UPDATABLE) 650 { 651 throw StandardException.newException(SQLState.LANG_UPDATABLE_VTI_NON_UPDATABLE_RS, 652 getVTIName()); 653 } 654 655 rsmd = ps.getMetaData(); 656 657 controlsDeferral = (ps instanceof DeferModification); 658 659 665 try 666 { 667 resultSetType = ps.getResultSetType(); 668 } 669 catch( SQLException sqle){} 670 catch( java.lang.AbstractMethodError ame){} 671 catch( java.lang.NoSuchMethodError nsme){} 672 isInsensitive = (resultSetType == ResultSet.TYPE_SCROLL_INSENSITIVE); 673 674 if (!implementsVTICosting) { 675 ps.close(); 676 ps = null; 677 } 678 679 } 680 else 681 { 682 rs = (ResultSet ) getNewInstance(); 683 684 rsmd = rs.getMetaData(); 685 686 if (!implementsVTICosting) { 687 rs.close(); 688 rs = null; 689 } 690 } 691 } 692 catch(Throwable t) 693 { 694 throw StandardException.unexpectedUserException(t); 695 } 696 697 return rsmd; 698 } 699 700 private Object getNewInstance() 701 throws StandardException 702 { 703 Class [] paramTypeClasses = newInvocation.getMethodParameterClasses(); 704 Object [] paramObjects = null; 705 706 if (paramTypeClasses != null) 707 { 708 paramObjects = new Object [paramTypeClasses.length]; 709 710 for (int index = 0; index < paramTypeClasses.length; index++) 711 { 712 Class paramClass = paramTypeClasses[index]; 713 714 paramObjects[index] = methodParms[index].getConstantValueAsObject(); 715 716 if ((paramObjects[index] != null) && paramClass.isPrimitive()) { 721 722 if (paramClass.equals(Short.TYPE)) { 723 paramObjects[index] = 724 new Short (((Integer ) paramObjects[index]).shortValue()); 725 } else if (paramClass.equals(Byte.TYPE)) { 726 paramObjects[index] = 727 new Byte (((Integer ) paramObjects[index]).byteValue()); 728 } 729 } 730 731 if (paramObjects[index] == null && 733 paramClass.isPrimitive()) 734 { 735 if (paramClass.equals(Integer.TYPE)) 736 { 737 paramObjects[index] = new Integer (0); 738 } 739 else if (paramClass.equals(Short.TYPE)) 740 { 741 paramObjects[index] = new Short ((short) 0); 742 } 743 else if (paramClass.equals(Byte.TYPE)) 744 { 745 paramObjects[index] = new Byte ((byte) 0); 746 } 747 else if (paramClass.equals(Long.TYPE)) 748 { 749 paramObjects[index] = new Long ((long) 0); 750 } 751 else if (paramClass.equals(Float.TYPE)) 752 { 753 paramObjects[index] = new Float ((float) 0); 754 } 755 else if (paramClass.equals(Double.TYPE)) 756 { 757 paramObjects[index] = new Double ((double) 0); 758 } 759 else if (paramClass.equals(Boolean.TYPE)) 760 { 761 paramObjects[index] = Boolean.FALSE; 762 } 763 else if (paramClass.equals(Character.TYPE)) 764 { 765 paramObjects[index] = new Character (Character.MIN_VALUE); 766 } 767 } 768 } 769 } 770 else 771 { 772 paramTypeClasses = new Class [0]; 773 paramObjects = new Object [0]; 774 } 775 776 try 777 { 778 ClassInspector classInspector = getClassFactory().getClassInspector(); 779 String javaClassName = newInvocation.getJavaClassName(); 780 Constructor constructor = classInspector.getClass(javaClassName).getConstructor(paramTypeClasses); 781 782 return constructor.newInstance(paramObjects); 783 } 784 catch(Throwable t) 785 { 786 if( t instanceof InvocationTargetException ) 787 { 788 InvocationTargetException ite = (InvocationTargetException ) t; 789 Throwable wrappedThrowable = ite.getTargetException(); 790 if( wrappedThrowable instanceof StandardException) 791 throw (StandardException) wrappedThrowable; 792 } 793 throw StandardException.unexpectedUserException(t); 794 } 795 } 797 802 public DeferModification getDeferralControl( ) 803 throws StandardException 804 { 805 if( ! controlsDeferral) 806 return null; 807 try 808 { 809 return (DeferModification) getNewInstance(); 810 } 811 catch(Throwable t) 812 { 813 throw StandardException.unexpectedUserException(t); 814 } 815 } 817 821 public int getResultSetType() 822 { 823 return resultSetType; 824 } 825 826 834 835 public void bindExpressions(FromList fromListParam) 836 throws StandardException 837 { 838 ResultColumnList derivedRCL = resultColumns; 839 840 844 materializable = newInvocation.areParametersQueryInvariant(); 845 846 850 Vector colRefs = getNodesFromParameters(ColumnReference.class); 851 Vector aggregateVector = null; 852 for (Enumeration e = colRefs.elements(); e.hasMoreElements(); ) 853 { 854 ColumnReference ref = (ColumnReference)e.nextElement(); 855 856 if (ref.getTableNumber() == -1) 858 { 859 if (aggregateVector == null) 861 { 862 aggregateVector = new Vector (); 863 } 864 ref.bindExpression(fromListParam, 865 subqueryList, 866 aggregateVector); 867 } 868 } 869 } 870 871 881 Vector getNodesFromParameters(Class nodeClass) 882 throws StandardException 883 { 884 CollectNodesVisitor getCRs = new CollectNodesVisitor(nodeClass); 885 newInvocation.accept(getCRs); 886 return getCRs.getList(); 887 } 888 889 894 public ResultColumnList getAllResultColumns(TableName allTableName) 895 throws StandardException 896 { 897 ResultColumnList rcList = null; 898 ResultColumn resultColumn; 899 ValueNode valueNode; 900 String columnName; 901 TableName toCompare; 902 903 if(allTableName != null) 904 toCompare = makeTableName(allTableName.getSchemaName(),correlationName); 905 else 906 toCompare = makeTableName(null,correlationName); 907 908 if ( allTableName != null && 909 ! allTableName.equals(toCompare)) 910 { 911 return null; 912 } 913 914 rcList = (ResultColumnList) getNodeFactory().getNode( 915 C_NodeTypes.RESULT_COLUMN_LIST, 916 getContextManager()); 917 918 922 int rclSize = resultColumns.size(); 923 for (int index = 0; index < rclSize; index++) 924 { 925 resultColumn = (ResultColumn) resultColumns.elementAt(index); 926 927 if (resultColumn.isGenerated()) 928 { 929 continue; 930 } 931 932 columnName = resultColumn.getName(); 934 valueNode = (ValueNode) getNodeFactory().getNode( 935 C_NodeTypes.COLUMN_REFERENCE, 936 columnName, 937 exposedName, 938 getContextManager()); 939 resultColumn = (ResultColumn) getNodeFactory().getNode( 940 C_NodeTypes.RESULT_COLUMN, 941 columnName, 942 valueNode, 943 getContextManager()); 944 945 rcList.addResultColumn(resultColumn); 947 } 948 return rcList; 949 } 950 951 964 965 public ResultColumn getMatchingColumn(ColumnReference columnReference) throws StandardException 966 { 967 970 if (resultColumns == null) 971 { 972 return null; 973 } 974 975 ResultColumn resultColumn = null; 976 TableName columnsTableName; 977 TableName exposedTableName; 978 979 columnsTableName = columnReference.getTableNameNode(); 980 981 986 if (columnsTableName == null || columnsTableName.equals(exposedName)) 987 { 988 resultColumn = resultColumns.getResultColumn(columnReference.getColumnName()); 989 990 if (resultColumn != null) 991 { 992 columnReference.setTableNumber(tableNumber); 993 } 994 } 995 996 return resultColumn; 997 } 998 999 1017 1018 public ResultSetNode preprocess(int numTables, 1019 GroupByList gbl, 1020 FromList fromList) 1021 throws StandardException 1022 { 1023 newInvocation.preprocess( 1024 numTables, 1025 (FromList) getNodeFactory().getNode( 1026 C_NodeTypes.FROM_LIST, 1027 getNodeFactory().doJoinOrderOptimization(), 1028 getContextManager()), 1029 (SubqueryList) getNodeFactory().getNode( 1030 C_NodeTypes.SUBQUERY_LIST, 1031 getContextManager()), 1032 (PredicateList) getNodeFactory().getNode( 1033 C_NodeTypes.PREDICATE_LIST, 1034 getContextManager())); 1035 1036 referencedTableMap = new JBitSet(numTables); 1037 referencedTableMap.set(tableNumber); 1038 newInvocation.categorize(referencedTableMap, false); 1039 1040 dependencyMap = new JBitSet(numTables); 1042 for (int index = 0; index < numTables; index++) 1043 { 1044 if ((index != tableNumber) && referencedTableMap.get(index)) 1045 { 1046 dependencyMap.set(index); 1047 } 1048 } 1049 1050 correlationMap = new JBitSet(numTables); 1052 newInvocation.getCorrelationTables(correlationMap); 1053 1054 return genProjectRestrict(numTables); 1055 } 1056 1057 1079 1080 protected ResultSetNode genProjectRestrict(int numTables) 1081 throws StandardException 1082 { 1083 ResultColumnList prRCList; 1084 1085 1088 prRCList = resultColumns; 1089 resultColumns = resultColumns.copyListAndObjects(); 1090 1091 1097 prRCList.genVirtualColumnNodes(this, resultColumns, false); 1098 1099 1102 prRCList.doProjection(); 1103 1104 1105 return (ResultSetNode) getNodeFactory().getNode( 1106 C_NodeTypes.PROJECT_RESTRICT_NODE, 1107 this, 1108 prRCList, 1109 null, 1110 null, 1111 null, 1112 null, 1113 tableProperties, 1114 getContextManager() ); 1115 } 1116 1117 1125 public boolean performMaterialization(JBitSet outerTables) 1126 throws StandardException 1127 { 1128 1136 return (outerTables.getFirstSetBit() != -1 && 1137 ! outerTables.hasSingleBitSet() && (! getTrulyTheBestAccessPath(). 1139 getJoinStrategy(). 1140 doesMaterialization()) && isMaterializable() && ! supportsMultipleInstantiations ); 1144 } 1145 1146 1155 public void generate(ActivationClassBuilder acb, 1156 MethodBuilder mb) 1157 throws StandardException 1158 { 1159 1165 RemapCRsVisitor rcrv = new RemapCRsVisitor(true); 1166 newInvocation.accept(rcrv); 1167 1168 1171 assignResultSetNumber(); 1172 1173 acb.pushGetResultSetFactoryExpression(mb); 1174 int nargs = getScanArguments(acb, mb); 1175 mb.callMethod(VMOpcode.INVOKEINTERFACE, (String ) null, "getVTIResultSet",ClassName.NoPutResultSet, nargs); 1176 } 1177 1178 private int getScanArguments(ActivationClassBuilder acb, 1179 MethodBuilder mb) 1180 throws StandardException 1181 { 1182 int rclSize = resultColumns.size(); 1183 FormatableBitSet referencedCols = new FormatableBitSet(rclSize); 1184 int erdNumber = -1; 1185 int numSet = 0; 1186 1187 costEstimate = getFinalCostEstimate(); 1189 1190 for (int index = 0; index < rclSize; index++) 1191 { 1192 ResultColumn rc = (ResultColumn) resultColumns.elementAt(index); 1193 if (rc.isReferenced()) 1194 { 1195 referencedCols.set(index); 1196 numSet++; 1197 } 1198 } 1199 1200 if (numSet != numVTICols) 1202 { 1203 erdNumber = acb.addItem(referencedCols); 1204 } 1205 1206 int ctcNumber = acb.addItem(compileTimeConstants); 1208 1209 acb.pushThisAsActivation(mb); 1211 resultColumns.generateHolder(acb, mb); 1214 1219 1225 boolean reuseablePs = version2 && 1226 (getNodesFromParameters(ParameterNode.class).size() == 0) && 1227 (getNodesFromParameters(ColumnReference.class).size() == 0); 1228 1229 1230 1231 mb.push(resultSetNumber); 1233 generateConstructor(acb, mb, reuseablePs); 1236 mb.push(newInvocation.getJavaClassName()); 1239 if (restrictionList != null) { 1240 restrictionList.generateQualifiers(acb, mb, this, true); 1241 } 1242 else 1243 mb.pushNull(ClassName.Qualifier + "[][]"); 1244 1245 mb.push(erdNumber); 1248 mb.push(version2); 1250 1251 mb.push(reuseablePs); 1252 1253 mb.push(ctcNumber); 1254 1255 mb.push(isTarget); 1257 1258 mb.push(getCompilerContext().getScanIsolationLevel()); 1260 1261 mb.push(costEstimate.rowCount()); 1263 1264 mb.push(costEstimate.getEstimatedCost()); 1266 1267 return 14; 1268 } 1269 1270 private void generateConstructor(ActivationClassBuilder acb, 1271 MethodBuilder mb, boolean reuseablePs) 1272 throws StandardException 1273 { 1274 1275 String vtiType = version2 ? 1276 "java.sql.PreparedStatement" : "java.sql.ResultSet"; 1277 MethodBuilder userExprFun = acb.newGeneratedFun( 1281 vtiType, Modifier.PUBLIC); 1282 userExprFun.addThrownException("java.lang.Exception"); 1283 1284 1285 LocalField psHolder = reuseablePs ? acb.newFieldDeclaration(Modifier.PRIVATE, "java.sql.PreparedStatement") : null; 1287 1288 if (reuseablePs) { 1289 1290 userExprFun.getField(psHolder); 1291 userExprFun.conditionalIfNull(); 1292 } 1293 1294 newInvocation.generateExpression(acb, userExprFun); 1295 userExprFun.upCast(vtiType); 1296 1297 if (reuseablePs) { 1298 1299 userExprFun.putField(psHolder); 1300 1301 userExprFun.startElseCode(); 1302 1303 userExprFun.getField(psHolder); 1304 1305 userExprFun.completeConditional(); 1306 } 1307 1308 userExprFun.methodReturn(); 1309 1310 1311 1312 1314 1317 userExprFun.complete(); 1319 1320 acb.pushMethodReference(mb, userExprFun); 1327 1328 1329 if (reuseablePs) { 1332 MethodBuilder closeActivationMethod = acb.getCloseActivationMethod(); 1333 1334 closeActivationMethod.getField(psHolder); 1335 closeActivationMethod.conditionalIfNull(); 1336 closeActivationMethod.push(0); closeActivationMethod.startElseCode(); 1339 closeActivationMethod.getField(psHolder); 1340 closeActivationMethod.callMethod(VMOpcode.INVOKEINTERFACE, "java.sql.Statement", 1341 "close", "void", 0); 1342 closeActivationMethod.push(0); 1343 1344 closeActivationMethod.completeConditional(); 1345 closeActivationMethod.endStatement(); 1346 } 1347 1348 } 1349 1350 1360 public boolean referencesTarget(String name, boolean baseTable) 1361 throws StandardException 1362 { 1363 return (! baseTable) && name.equals(newInvocation.getJavaClassName()); 1364 } 1365 1366 1374 public Visitable accept(Visitor v) 1375 throws StandardException 1376 { 1377 if (v.skipChildren(this)) 1378 { 1379 return v.visit(this); 1380 } 1381 1382 Visitable returnNode = super.accept(v); 1383 1384 if (!v.stopTraversal()) 1385 { 1386 newInvocation = (NewInvocationNode) newInvocation.accept(v); 1387 } 1388 1389 return returnNode; 1390 } 1391 1392 1401 private UUID getSpecialTriggerVTITableName(LanguageConnectionContext lcc, String className) 1402 throws StandardException 1403 { 1404 if (className.equals(ClassName.TriggerNewTransitionRows) || 1405 className.equals(ClassName.TriggerOldTransitionRows)) 1406 { 1407 if (lcc.getTriggerTable() != null) 1409 { 1410 return lcc.getTriggerTable().getUUID(); 1411 } 1412 else if (lcc.getTriggerExecutionContext() != null) 1413 { 1414 return lcc.getTriggerExecutionContext().getTargetTableId(); 1415 } 1416 else 1417 { 1418 throw StandardException.newException(SQLState.LANG_CANNOT_BIND_TRIGGER_V_T_I, className); 1419 } 1420 } 1421 return (UUID)null; 1422 } 1423 1424 private ResultColumnList genResultColList(TableDescriptor td) 1425 throws StandardException 1426 { 1427 ResultColumnList rcList = null; 1428 ResultColumn resultColumn; 1429 ValueNode valueNode; 1430 ColumnDescriptor colDesc = null; 1431 1432 1433 TableName tableName = makeTableName(td.getSchemaName(), 1434 td.getName()); 1435 1436 1437 rcList = (ResultColumnList) getNodeFactory().getNode( 1438 C_NodeTypes.RESULT_COLUMN_LIST, 1439 getContextManager()); 1440 ColumnDescriptorList cdl = td.getColumnDescriptorList(); 1441 int cdlSize = cdl.size(); 1442 1443 for (int index = 0; index < cdlSize; index++) 1444 { 1445 1446 colDesc = (ColumnDescriptor) cdl.elementAt(index); 1447 1448 valueNode = (ValueNode) getNodeFactory().getNode( 1449 C_NodeTypes.BASE_COLUMN_NODE, 1450 colDesc.getColumnName(), 1451 exposedName, 1452 colDesc.getType(), 1453 getContextManager()); 1454 resultColumn = (ResultColumn) getNodeFactory().getNode( 1455 C_NodeTypes.RESULT_COLUMN, 1456 colDesc, 1457 valueNode, 1458 getContextManager()); 1459 1460 1461 rcList.addResultColumn(resultColumn); 1462 } 1463 1464 return rcList; 1465 } 1466 1467 public boolean needsSpecialRCLBinding() 1468 { 1469 return true; 1470 } 1471 1472 boolean isUpdatableCursor() throws StandardException { 1473 return true; 1474 } 1475 1476 protected void markUpdatableByCursor(Vector updateColumns) { 1477 super.markUpdatableByCursor(updateColumns); 1478 forUpdatePresent = true; 1479 emptyForUpdate = ((updateColumns == null) || (updateColumns.size() == 0)); 1480 } 1481 1482 private int[] getForUpdateColumnList() { 1483 1484 int[] tempList = new int[getNumColumnsReturned()]; 1485 int offset = 0; 1486 1487 for (int col = 0; col < tempList.length; col++) 1488 { 1489 if (resultColumns.updatableByCursor(col)) 1490 tempList[offset++] = col + 1; } 1492 1493 int[] list; 1494 1495 if (offset == tempList.length) 1496 list = tempList; 1497 else { 1498 list = new int[offset]; 1499 System.arraycopy(tempList, 0, list, 0, offset); 1500 } 1501 1502 return list; 1503 } 1504 1505 1508 public final boolean isCompileTime() { 1509 return true; 1510 } 1511 1512 public String getOriginalSQL() { 1513 return getCompilerContext().getParser().getSQLtext(); 1514 } 1515 1516 public final int getStatementIsolationLevel() { 1517 return ExecutionContext.CS_TO_JDBC_ISOLATION_LEVEL_MAP[getCompilerContext().getScanIsolationLevel()]; 1518 } 1519 1520 public void setSharedState(String key, java.io.Serializable value) { 1521 1522 if (key == null) 1523 return; 1524 1525 if (compileTimeConstants == null) 1526 compileTimeConstants = new FormatableHashtable(); 1527 1528 compileTimeConstants.put(key, value); 1529 } 1530 1531 public Object getSharedState(String key) { 1532 if ((key == null) || (compileTimeConstants == null)) 1533 return null; 1534 1535 return compileTimeConstants.get(key); 1536 } 1537} 1538 | Popular Tags |