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.services.loader.GeneratedMethod; 27 28 import org.apache.derby.iapi.services.compiler.JavaFactory; 29 import org.apache.derby.iapi.services.compiler.MethodBuilder; 30 31 import org.apache.derby.iapi.reference.SQLState; 32 import org.apache.derby.iapi.error.StandardException; 33 34 import org.apache.derby.iapi.sql.compile.C_NodeTypes; 35 36 import org.apache.derby.iapi.sql.conn.Authorizer; 37 38 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext; 39 import org.apache.derby.iapi.sql.compile.Visitable; 40 import org.apache.derby.iapi.sql.compile.Visitor; 41 import org.apache.derby.iapi.sql.compile.CompilerContext; 42 43 import org.apache.derby.iapi.reference.ClassName; 44 45 import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor; 46 import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor; 47 import org.apache.derby.iapi.sql.dictionary.DataDictionary; 48 import org.apache.derby.iapi.sql.dictionary.TableDescriptor; 49 import org.apache.derby.iapi.sql.dictionary.IndexLister; 50 import org.apache.derby.iapi.sql.dictionary.IndexRowGenerator; 51 import org.apache.derby.iapi.types.TypeId; 52 53 import org.apache.derby.iapi.sql.ResultSet; 54 import org.apache.derby.iapi.sql.Activation; 55 import org.apache.derby.iapi.sql.StatementType; 56 57 import org.apache.derby.iapi.sql.execute.ConstantAction; 58 59 import org.apache.derby.iapi.store.access.StaticCompiledOpenConglomInfo; 60 import org.apache.derby.iapi.store.access.TransactionController; 61 import org.apache.derby.iapi.types.RowLocation; 62 63 import org.apache.derby.impl.sql.compile.ActivationClassBuilder; 64 import org.apache.derby.iapi.services.compiler.MethodBuilder; 65 66 import org.apache.derby.iapi.services.sanity.SanityManager; 67 68 import org.apache.derby.vti.DeferModification; 69 70 import org.apache.derby.iapi.services.classfile.VMOpcode; 71 import org.apache.derby.iapi.util.StringUtil; 72 73 import org.apache.derby.catalog.UUID; 74 75 import org.apache.derby.impl.sql.execute.FKInfo; 76 77 import java.util.Properties ; 78 79 import org.apache.derby.iapi.services.io.FormatableBitSet; 80 import org.apache.derby.iapi.util.ReuseFactory; 81 82 104 public final class InsertNode extends DMLModStatementNode 105 { 106 public ResultColumnList targetColumnList; 107 public boolean deferred; 108 public ValueNode checkConstraints; 109 public Properties targetProperties; 110 public FKInfo fkInfo; 111 protected boolean bulkInsert; 112 private boolean bulkInsertReplace; 113 114 protected RowLocation[] autoincRowLocation; 115 128 129 public void init( 130 Object targetName, 131 Object insertColumns, 132 Object queryExpression, 133 Object targetProperties) 134 { 135 139 super.init( 140 queryExpression, 141 ReuseFactory.getInteger(getStatementType( 142 (Properties ) targetProperties)) 143 ); 144 setTarget((QueryTreeNode) targetName); 145 targetColumnList = (ResultColumnList) insertColumns; 146 this.targetProperties = (Properties ) targetProperties; 147 148 149 getResultSetNode().setInsertSource(); 150 } 151 152 158 159 public String toString() 160 { 161 if (SanityManager.DEBUG) 162 { 163 try { 164 return ( (targetTableName!=null) ? targetTableName : targetVTI.getTableName() ).toString() + "\n" 165 + targetProperties + "\n" 166 + super.toString(); 167 } catch (org.apache.derby.iapi.error.StandardException e) { 168 return "tableName: <not_known>\n" 169 + targetProperties + "\n" 170 + super.toString(); 171 } 172 } 173 else 174 { 175 return ""; 176 } 177 } 178 179 public String statementToString() 180 { 181 return "INSERT"; 182 } 183 184 190 191 public void printSubNodes(int depth) 192 { 193 if (SanityManager.DEBUG) 194 { 195 super.printSubNodes(depth); 196 197 if (targetTableName != null) 198 { 199 printLabel(depth, "targetTableName: "); 200 targetTableName.treePrint(depth + 1); 201 } 202 203 if (targetColumnList != null) 204 { 205 printLabel(depth, "targetColumnList: "); 206 targetColumnList.treePrint(depth + 1); 207 } 208 209 210 } 211 } 212 213 227 228 public QueryTreeNode bind() throws StandardException 229 { 230 getCompilerContext().pushCurrentPrivType( Authorizer.SELECT_PRIV); 232 233 FromList fromList = (FromList) getNodeFactory().getNode( 234 C_NodeTypes.FROM_LIST, 235 getNodeFactory().doJoinOrderOptimization(), 236 getContextManager()); 237 238 242 DataDictionary dataDictionary = getDataDictionary(); 243 super.bindResultSetsWithTables(dataDictionary); 244 245 248 verifyTargetTable(); 249 250 if (targetProperties != null) 252 { 253 verifyTargetProperties(dataDictionary); 254 } 255 256 260 getResultColumnList(); 261 262 265 if (targetColumnList != null) 266 { 267 270 if (synonymTableName != null) 271 { 272 normalizeSynonymColumns ( targetColumnList, targetTableName ); 273 } 274 275 276 getCompilerContext().pushCurrentPrivType( getPrivType()); 277 if (targetTableDescriptor != null) 278 { 279 targetColumnList.bindResultColumnsByName(targetTableDescriptor, 280 (DMLStatementNode) this); 281 } 282 else 283 { 284 targetColumnList.bindResultColumnsByName(targetVTI.getResultColumns(), targetVTI, 285 this); 286 } 287 getCompilerContext().popCurrentPrivType(); 288 } 289 290 291 if (SanityManager.DEBUG) 292 { 293 SanityManager.ASSERT(fromList.size() == 0, 294 "fromList.size() is expected to be 0, not " + 295 fromList.size() + 296 " on return from RS.bindExpressions()"); 297 } 298 299 300 resultSet.replaceDefaults(targetTableDescriptor, targetColumnList); 301 302 308 super.bindExpressions(); 309 310 322 if (targetColumnList != null) 323 { 324 if (resultSet.getResultColumns().size() > targetColumnList.size()) 325 throw StandardException.newException(SQLState.LANG_DB2_INVALID_COLS_SPECIFIED); 326 resultSet.bindUntypedNullsToResultColumns(targetColumnList); 327 resultSet.setTableConstructorTypes(targetColumnList); 328 } 329 else 330 { 331 if (resultSet.getResultColumns().size() > resultColumnList.size()) 332 throw StandardException.newException(SQLState.LANG_DB2_INVALID_COLS_SPECIFIED); 333 resultSet.bindUntypedNullsToResultColumns(resultColumnList); 334 resultSet.setTableConstructorTypes(resultColumnList); 335 } 336 337 338 resultSet.bindResultColumns(fromList); 339 340 int resCols = resultSet.getResultColumns().size(); 341 DataDictionary dd = getDataDictionary(); 342 if (targetColumnList != null) 343 { 344 if (targetColumnList.size() != resCols) 345 throw StandardException.newException(SQLState.LANG_DB2_INVALID_COLS_SPECIFIED); 346 } 347 else 348 { 349 if (targetTableDescriptor != null && 350 targetTableDescriptor.getNumberOfColumns() != resCols) 351 throw StandardException.newException(SQLState.LANG_DB2_INVALID_COLS_SPECIFIED); 352 } 353 354 360 boolean inOrder = true; 361 int numTableColumns = resultColumnList.size(); 362 363 367 int[] colMap = new int[numTableColumns]; 368 369 for (int i = 0; i < colMap.length; i++) 371 { 372 colMap[i] = -1; 373 } 374 375 376 if (targetColumnList != null) 377 { 378 384 int targetSize = targetColumnList.size(); 385 for (int index = 0; index < targetSize; index++) 386 { 387 int position = 388 ((ResultColumn) (targetColumnList.elementAt(index))). 389 columnDescriptor.getPosition(); 390 391 if (index != position-1) 392 { 393 inOrder = false; 394 } 395 396 colMap[position-1] = index; 398 } 399 } 400 else 401 { 402 407 for (int position = 0; 408 position < resultSet.getResultColumns().size(); 409 position++) 410 { 411 colMap[position] = position; 412 } 413 } 414 415 421 429 433 if (! inOrder || resultSet.resultColumns.size() < numTableColumns) 434 { 435 442 resultSet = resultSet.enhanceRCLForInsert(numTableColumns, colMap, 443 dataDictionary, 444 targetTableDescriptor, targetVTI); 445 } 446 447 if (resultSet instanceof UnionNode) 448 { 449 resultColumnList.checkAutoincrementUnion(resultSet); 452 } 453 else resultColumnList.checkAutoincrement(resultSet.getResultColumns()); 454 resultColumnList.checkStorableExpressions(resultSet.getResultColumns()); 455 458 if (! resultColumnList.columnTypesAndLengthsMatch( 459 resultSet.getResultColumns())) 460 { 461 resultSet = resultSet.genNormalizeResultSetNode(resultSet, false); 462 resultColumnList.copyTypesAndLengthsToSource(resultSet.getResultColumns()); 463 } 464 465 if (targetTableDescriptor != null) 466 { 467 468 ResultColumnList sourceRCL = resultSet.getResultColumns(); 469 sourceRCL.copyResultColumnNames(resultColumnList); 470 checkConstraints = bindConstraints(dataDictionary, 471 getNodeFactory(), 472 targetTableDescriptor, 473 null, 474 sourceRCL, 475 (int[]) null, 476 (FormatableBitSet) null, 477 false, 478 true); 480 481 482 488 if (resultSet.referencesTarget( 489 targetTableDescriptor.getName(), true) || 490 requiresDeferredProcessing()) 491 { 492 deferred = true; 493 494 497 if (bulkInsertReplace && 498 resultSet.referencesTarget( 499 targetTableDescriptor.getName(), true)) 500 { 501 throw StandardException.newException(SQLState.LANG_INVALID_BULK_INSERT_REPLACE, 502 targetTableDescriptor.getQualifiedName()); 503 } 504 } 505 506 507 getAffectedIndexes(targetTableDescriptor); 508 TransactionController tc = 509 getLanguageConnectionContext().getTransactionCompile(); 510 511 autoincRowLocation = 512 dd.computeAutoincRowLocations(tc, targetTableDescriptor); 513 514 if (isPrivilegeCollectionRequired()) 515 { 516 getCompilerContext().pushCurrentPrivType(getPrivType()); 517 getCompilerContext().addRequiredTablePriv(targetTableDescriptor); 518 getCompilerContext().popCurrentPrivType(); 519 } 520 521 } 522 else 523 { 524 deferred = VTIDeferModPolicy.deferIt( DeferModification.INSERT_STATEMENT, 525 targetVTI, 526 null, 527 resultSet); 528 } 529 530 getCompilerContext().popCurrentPrivType(); 531 return this; 532 } 533 534 int getPrivType() 535 { 536 return Authorizer.INSERT_PRIV; 537 } 538 539 546 public boolean referencesSessionSchema() 547 throws StandardException 548 { 549 boolean returnValue = false; 550 551 if (targetTableDescriptor != null) 553 returnValue = isSessionSchema(targetTableDescriptor.getSchemaDescriptor()); 554 555 if (returnValue == false) 556 returnValue = resultSet.referencesSessionSchema(); 557 558 return returnValue; 559 } 560 561 571 private void verifyTargetProperties(DataDictionary dd) 572 throws StandardException 573 { 574 String insertMode = targetProperties.getProperty("insertMode"); 576 if (insertMode != null) 577 { 578 String upperValue = StringUtil.SQLToUpperCase(insertMode); 579 if (! upperValue.equals("BULKINSERT") && 580 ! upperValue.equals("REPLACE")) 581 { 582 throw StandardException.newException(SQLState.LANG_INVALID_INSERT_MODE, 583 insertMode, 584 targetTableName); 585 } 586 else 587 { 588 589 if (! verifyBulkInsert(dd, upperValue)) 590 { 591 targetProperties.remove("insertMode"); 592 } 593 else 594 { 595 596 bulkInsert = true; 597 598 if (upperValue.equals("REPLACE")) 599 { 600 bulkInsertReplace = true; 601 } 602 603 String bulkFetchStr = targetProperties.getProperty("bulkFetch"); 605 if (bulkFetchStr != null) 606 { 607 int bulkFetch = getIntProperty(bulkFetchStr, "bulkFetch"); 608 609 if (bulkFetch <= 0) 611 { 612 throw StandardException.newException(SQLState.LANG_INVALID_BULK_FETCH_VALUE, 613 String.valueOf(bulkFetch)); 614 } 615 } 616 } 617 } 618 } 619 } 620 621 636 private boolean verifyBulkInsert(DataDictionary dd, String mode) 637 throws StandardException 638 { 639 return true; 640 } 641 642 647 public ConstantAction makeConstantAction() throws StandardException 648 { 649 650 651 if (targetTableDescriptor != null) 652 { 653 655 long heapConglomId = targetTableDescriptor.getHeapConglomerateId(); 656 TransactionController tc = 657 getLanguageConnectionContext().getTransactionCompile(); 658 int numIndexes = (targetTableDescriptor != null) ? 659 indexConglomerateNumbers.length : 0; 660 StaticCompiledOpenConglomInfo[] indexSCOCIs = 661 new StaticCompiledOpenConglomInfo[numIndexes]; 662 663 for (int index = 0; index < numIndexes; index++) 664 { 665 indexSCOCIs[index] = tc.getStaticCompiledConglomInfo(indexConglomerateNumbers[index]); 666 } 667 668 675 if (bulkInsert || 676 targetTableDescriptor.getLockGranularity() == TableDescriptor.TABLE_LOCK_GRANULARITY) 677 { 678 lockMode = TransactionController.MODE_TABLE; 679 } 680 681 return getGenericConstantActionFactory().getInsertConstantAction 682 ( targetTableDescriptor, 683 heapConglomId, 684 tc.getStaticCompiledConglomInfo(heapConglomId), 685 indicesToMaintain, 686 indexConglomerateNumbers, 687 indexSCOCIs, 688 indexNames, 689 deferred, 690 false, 691 targetTableDescriptor.getUUID(), 692 lockMode, 693 null, null, 694 targetProperties, 695 getFKInfo(), 696 getTriggerInfo(), 697 resultColumnList.getStreamStorableColIds(targetTableDescriptor.getNumberOfColumns()), 698 getIndexedCols(), 699 (UUID) null, 700 null, 701 null, 702 resultSet.isOneRowResultSet(), 703 autoincRowLocation 704 ); 705 } 706 else 707 { 708 713 return getGenericConstantActionFactory().getUpdatableVTIConstantAction( DeferModification.INSERT_STATEMENT, 714 deferred); 715 } 716 } 717 718 725 public boolean[] getIndexedCols() throws StandardException 726 { 727 728 boolean[] indexedCols = new boolean[targetTableDescriptor.getNumberOfColumns()]; 729 for (int index = 0; index < indicesToMaintain.length; index++) 730 { 731 int[] colIds = indicesToMaintain[index].getIndexDescriptor().baseColumnPositions(); 732 733 for (int index2 = 0; index2 < colIds.length; index2++) 734 { 735 indexedCols[colIds[index2] - 1] = true; 736 } 737 } 738 739 return indexedCols; 740 } 741 742 752 public void generate(ActivationClassBuilder acb, 753 MethodBuilder mb) 754 throws StandardException 755 { 756 generateCodeForTemporaryTable(acb, mb); 758 759 760 generateParameterValueSet(acb); 761 if (targetTableDescriptor != null) 763 { 764 769 770 acb.pushGetResultSetFactoryExpression(mb); 771 772 resultSet.generate(acb, mb); 774 775 generateCheckConstraints( checkConstraints, acb, mb ); 777 778 mb.callMethod(VMOpcode.INVOKEINTERFACE, (String ) null, "getInsertResultSet", ClassName.ResultSet, 2); 779 } 780 else 781 { 782 788 targetVTI.assignCostEstimate(resultSet.getNewCostEstimate()); 789 790 794 acb.pushGetResultSetFactoryExpression(mb); 795 796 resultSet.generate(acb, mb); 798 799 targetVTI.generate(acb, mb); 801 802 mb.callMethod(VMOpcode.INVOKEINTERFACE, (String ) null, "getInsertVTIResultSet", ClassName.ResultSet, 2); 803 } 804 } 805 806 812 protected final int getStatementType() 813 { 814 return StatementType.INSERT; 815 } 816 817 824 static final int getStatementType(Properties targetProperties) 825 { 826 int retval = StatementType.INSERT; 827 828 String insertMode = (targetProperties == null) ? null : targetProperties.getProperty("insertMode"); 830 if (insertMode != null) 831 { 832 String upperValue = StringUtil.SQLToUpperCase(insertMode); 833 if (upperValue.equals("REPLACE")) 834 { 835 retval = StatementType.BULK_INSERT_REPLACE; 836 } 837 } 838 return retval; 839 } 840 841 851 private void getAffectedIndexes 852 ( 853 TableDescriptor td 854 ) 855 throws StandardException 856 { 857 IndexLister indexLister = td.getIndexLister( ); 858 859 indicesToMaintain = indexLister.getDistinctIndexRowGenerators(); 860 indexConglomerateNumbers = indexLister.getDistinctIndexConglomerateNumbers(); 861 indexNames = indexLister.getDistinctIndexNames(); 862 863 864 ConglomerateDescriptor[] cds = td.getConglomerateDescriptors(); 865 CompilerContext cc = getCompilerContext(); 866 867 for (int index = 0; index < cds.length; index++) 868 { 869 cc.createDependency(cds[index]); 870 } 871 } 872 873 } | Popular Tags |