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.sql.compile.C_NodeTypes; 27 28 import org.apache.derby.iapi.sql.conn.Authorizer; 29 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext; 30 31 import org.apache.derby.iapi.error.StandardException; 32 import org.apache.derby.iapi.reference.SQLState; 33 34 import org.apache.derby.iapi.sql.ResultColumnDescriptor; 35 36 import org.apache.derby.iapi.sql.dictionary.DataDictionary; 37 import org.apache.derby.iapi.sql.dictionary.DataDictionaryContext; 38 import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor; 39 import org.apache.derby.iapi.sql.dictionary.TableDescriptor; 40 41 import org.apache.derby.iapi.services.sanity.SanityManager; 42 43 import org.apache.derby.iapi.services.compiler.MethodBuilder; 44 45 import org.apache.derby.impl.sql.compile.ActivationClassBuilder; 46 47 import org.apache.derby.impl.sql.CursorInfo; 48 import org.apache.derby.impl.sql.CursorTableReference; 49 50 import java.util.ArrayList ; 51 import java.util.Vector ; 52 53 62 63 public class CursorNode extends DMLStatementNode 64 { 65 public final static int UNSPECIFIED = 0; 66 public final static int READ_ONLY = 1; 67 public final static int UPDATE = 2; 68 69 private String name; 70 private OrderByList orderByList; 71 private String statementType; 72 private int updateMode; 73 private boolean needTarget; 74 75 79 private Vector updatableColumns; 80 private FromTable updateTable; 81 private ResultColumnDescriptor[] targetColumnDescriptors; 82 83 private int indexOfSessionTableNamesInSavedObjects = -1; 87 88 105 106 public void init( 107 Object statementType, 108 Object resultSet, 109 Object name, 110 Object orderByList, 111 Object updateMode, 112 Object updatableColumns) 113 { 114 init(resultSet); 115 this.name = (String ) name; 116 this.statementType = (String ) statementType; 117 this.orderByList = (OrderByList) orderByList; 118 119 this.updateMode = ((Integer ) updateMode).intValue(); 120 this.updatableColumns = (Vector ) updatableColumns; 121 122 126 if (SanityManager.DEBUG) 127 SanityManager.ASSERT(this.updatableColumns == null || 128 this.updatableColumns.size() == 0 || this.updateMode == UPDATE, 129 "Can only have explicit updatable columns if update mode is UPDATE"); 130 } 131 132 138 139 public String toString() 140 { 141 if (SanityManager.DEBUG) 142 { 143 return "name: " + name + "\n" + 144 "updateMode: " + updateModeString(updateMode) + "\n" + 145 super.toString(); 146 } 147 else 148 { 149 return ""; 150 } 151 } 152 153 public String statementToString() 154 { 155 return statementType; 156 } 157 158 165 166 private static String updateModeString(int updateMode) 167 { 168 if (SanityManager.DEBUG) 169 { 170 switch (updateMode) 171 { 172 case UNSPECIFIED: 173 return "UNSPECIFIED (" + UNSPECIFIED + ")"; 174 175 case READ_ONLY: 176 return "READ_ONLY (" + READ_ONLY + ")"; 177 178 case UPDATE: 179 return "UPDATE (" + UPDATE + ")"; 180 181 default: 182 return "UNKNOWN VALUE (" + updateMode + ")"; 183 } 184 } 185 else 186 { 187 return ""; 188 } 189 } 190 191 197 198 public void printSubNodes(int depth) 199 { 200 if (SanityManager.DEBUG) 201 { 202 super.printSubNodes(depth); 203 204 printLabel(depth, "orderByList: "); 205 if (orderByList != null) 206 orderByList.treePrint(depth + 1); 207 } 208 } 209 210 221 222 public QueryTreeNode bind() throws StandardException 223 { 224 DataDictionary dataDictionary; 225 226 dataDictionary = getDataDictionary(); 227 228 if (orderByList != null) 239 { 240 orderByList.pullUpOrderByColumns(resultSet); 241 } 242 243 getCompilerContext().pushCurrentPrivType(getPrivType()); 244 try { 245 FromList fromList = (FromList) getNodeFactory().getNode( 246 C_NodeTypes.FROM_LIST, 247 getNodeFactory().doJoinOrderOptimization(), 248 getContextManager()); 249 250 251 resultSet.rejectParameters(); 252 253 super.bind(dataDictionary); 254 255 resultSet.bindResultColumns(fromList); 257 258 resultSet.bindUntypedNullsToResultColumns(null); 262 263 resultSet.rejectXMLValues(); 266 267 268 if (SanityManager.DEBUG) { 269 SanityManager.ASSERT(fromList.size() == 0, 270 "fromList.size() is expected to be 0, not " 271 + fromList.size() 272 + " on return from RS.bindExpressions()"); 273 } 274 } 275 finally 276 { 277 getCompilerContext().popCurrentPrivType(); 278 } 279 280 if (orderByList != null) 282 { 283 orderByList.bindOrderByColumns(resultSet); 284 } 285 286 288 if (updateMode == UPDATE) 290 { 291 int checkedUpdateMode; 292 293 checkedUpdateMode = determineUpdateMode(dataDictionary); 294 if (SanityManager.DEBUG) 295 SanityManager.DEBUG("DumpUpdateCheck","update mode is UPDATE ("+updateMode+") checked mode is "+checkedUpdateMode); 296 if (updateMode != checkedUpdateMode) 297 throw StandardException.newException(SQLState.LANG_STMT_NOT_UPDATABLE); 298 } 299 300 if (updateMode == UNSPECIFIED) 302 { 303 306 308 313 319 if (getLanguageConnectionContext().getStatementContext().isForReadOnly()) { 320 updateMode = READ_ONLY; 321 } else { 322 updateMode = determineUpdateMode(dataDictionary); 323 } 324 325 } 328 329 if (updateMode == READ_ONLY) { 330 updatableColumns = null; } 332 333 if (updateMode == UPDATE) 335 { 336 bindUpdateColumns(updateTable); 337 338 if (updateTable instanceof FromTable) 343 { 344 ((FromTable) updateTable).markUpdatableByCursor(updatableColumns); 345 resultSet.getResultColumns().markColumnsInSelectListUpdatableByCursor( 349 updatableColumns); 350 } 351 } 352 353 resultSet.renameGeneratedResultNames(); 354 355 if (getLanguageConnectionContext().checkIfAnyDeclaredGlobalTempTablesForThisConnection()) 357 { 358 ArrayList sessionSchemaTableNames = getSessionSchemaTableNamesForCursor(); 361 if (sessionSchemaTableNames != null) 362 indexOfSessionTableNamesInSavedObjects = getCompilerContext().addSavedObject(sessionSchemaTableNames); 363 } 364 365 return this; 366 } 367 368 375 public boolean referencesSessionSchema() 376 throws StandardException 377 { 378 return resultSet.referencesSessionSchema(); 380 } 381 382 protected ArrayList getSessionSchemaTableNamesForCursor() 386 throws StandardException 387 { 388 FromList fromList = resultSet.getFromList(); 389 int fromListSize = fromList.size(); 390 FromTable fromTable; 391 ArrayList sessionSchemaTableNames = null; 392 393 for( int i = 0; i < fromListSize; i++) 394 { 395 fromTable = (FromTable) fromList.elementAt(i); 396 if (fromTable instanceof FromBaseTable && isSessionSchema(fromTable.getTableDescriptor().getSchemaDescriptor())) 397 { 398 if (sessionSchemaTableNames == null) 399 sessionSchemaTableNames = new ArrayList (); 400 sessionSchemaTableNames.add(fromTable.getTableName().getTableName()); 401 } 402 } 403 404 return sessionSchemaTableNames; 405 } 406 407 444 private int determineUpdateMode(DataDictionary dataDictionary) 445 throws StandardException 446 { 447 SelectNode selectNode; 448 FromList tables; 449 FromTable targetTable; 450 451 if (updateMode == READ_ONLY) 452 { 453 return READ_ONLY; 454 } 455 456 if (orderByList != null) 457 { 458 if (SanityManager.DEBUG) 459 SanityManager.DEBUG("DumpUpdateCheck","cursor has order by"); 460 return READ_ONLY; 461 } 462 463 if (! resultSet.isUpdatableCursor(dataDictionary)) 466 { 467 return READ_ONLY; 468 } 469 470 482 updateTable = resultSet.getCursorTargetTable(); 483 484 485 if (updateTable.markAsCursorTargetTable()) { 486 487 needTarget = true; 488 489 493 genTargetResultColList(); 494 } 495 496 497 498 499 return UPDATE; 500 } 501 502 518 519 public QueryTreeNode optimize() throws StandardException 520 { 521 if (orderByList != null) 523 { 524 if (orderByList.size() > 1) 527 { 528 orderByList.removeDupColumns(); 529 } 530 531 resultSet.pushOrderByList(orderByList); 532 orderByList = null; 533 } 534 return super.optimize(); 535 } 536 537 545 546 int activationKind() 547 { 548 return NEED_CURSOR_ACTIVATION; 549 } 550 551 559 560 public void generate(ActivationClassBuilder acb, 561 MethodBuilder mb) throws StandardException 562 { 563 if (indexOfSessionTableNamesInSavedObjects != -1 ) { 565 MethodBuilder constructor = acb.getConstructor(); 566 constructor.pushThis(); 567 constructor.push(indexOfSessionTableNamesInSavedObjects); 568 constructor.putField(org.apache.derby.iapi.reference.ClassName.BaseActivation, "indexOfSessionTableNamesInSavedObjects", "int"); 569 constructor.endStatement(); 570 } 571 572 generateParameterValueSet(acb); 574 575 resultSet.markStatementResultSet(); 578 579 generateAuthorizeCheck(acb, mb, 580 org.apache.derby.iapi.sql.conn.Authorizer.SQL_SELECT_OP); 581 582 resultSet.generate(acb, mb); 584 585 592 if (needTarget) 593 { 594 acb.rememberCursor(mb); 596 acb.addCursorPositionCode(); 597 } 598 } 599 600 602 public String getUpdateBaseTableName() 603 { 604 return (updateTable == null) ? null : updateTable.getBaseTableName(); 605 } 606 607 public String getUpdateExposedTableName() 608 throws StandardException 609 { 610 return (updateTable == null) ? null : updateTable.getExposedName(); 611 } 612 613 public String getUpdateSchemaName() 614 throws StandardException 615 { 616 return (updateTable == null) ? null : ((FromBaseTable)updateTable).getTableNameField().getSchemaName(); 618 } 619 620 public int getUpdateMode() 621 { 622 return updateMode; 623 } 624 625 630 private String [] getUpdatableColumns() 631 { 632 return (updatableColumns == null) ? 633 (String [])null : 634 getUpdateColumnNames(); 635 } 636 637 649 private ResultColumnDescriptor[] genTargetResultColList() 650 throws StandardException 651 { 652 ResultColumnList newList; 653 654 662 if (updateTable == null) return null; 663 664 if (targetColumnDescriptors != null) return targetColumnDescriptors; 665 666 newList = (ResultColumnList) getNodeFactory().getNode( 667 C_NodeTypes.RESULT_COLUMN_LIST, 668 getContextManager()); 669 ResultColumnList rcl = updateTable.getResultColumns(); 670 int rclSize = rcl.size(); 671 for (int index = 0; index < rclSize; index++) 672 { 673 ResultColumn origCol, newCol; 674 ValueNode newNode; 675 676 origCol = (ResultColumn) rcl.elementAt(index); 677 678 newNode = (ValueNode) getNodeFactory().getNode( 680 C_NodeTypes.BASE_COLUMN_NODE, 681 origCol.getName(), 682 makeTableName(origCol.getSchemaName(), 683 origCol.getTableName()), 684 origCol.getTypeServices(), 685 getContextManager()); 686 newCol = (ResultColumn) getNodeFactory().getNode( 687 C_NodeTypes.RESULT_COLUMN, 688 origCol.columnDescriptor, 689 newNode, 690 getContextManager()); 691 692 693 newList.addResultColumn(newCol); 694 } 695 696 targetColumnDescriptors = newList.makeResultDescriptors(); 698 return targetColumnDescriptors; 699 } 700 701 709 public boolean needsSavepoint() 710 { 711 return false; 712 } 713 714 722 public Object getCursorInfo() 723 throws StandardException 724 { 725 if (!needTarget) 726 return null; 727 728 return new CursorInfo(updateMode, 729 new CursorTableReference( 730 getUpdateExposedTableName(), 731 getUpdateBaseTableName(), 732 getUpdateSchemaName()), 733 genTargetResultColList(), 734 getUpdatableColumns()); 735 } 736 737 748 private void bindUpdateColumns(FromTable targetTable) 749 throws StandardException 750 { 751 int size = updatableColumns.size(); 752 TableDescriptor tableDescriptor; 753 String columnName; 754 ResultColumnList rcls = resultSet.getResultColumns(); 755 756 for (int index = 0; index < size; index++) 757 { 758 columnName = (String ) updatableColumns.elementAt(index); 759 tableDescriptor = targetTable.getTableDescriptor(); 760 if ( tableDescriptor.getColumnDescriptor(columnName) == null) 761 { 762 throw StandardException.newException(SQLState.LANG_COLUMN_NOT_FOUND, columnName); 763 } 764 765 ResultColumn rc; 766 for (int rclsIndex = 0; rclsIndex < rcls.size(); rclsIndex++) { rc = ((ResultColumn) rcls.elementAt(rclsIndex)); 772 if (rc.getSourceTableName() == null) continue; 774 if (rc.getExpression() != null && rc.getExpression().getColumnName().equals(columnName) && !rc.getName().equals(columnName)) { 775 throw StandardException.newException(SQLState.LANG_CORRELATION_NAME_FOR_UPDATABLE_COLUMN_DISALLOWED_IN_CURSOR, columnName); 776 } 777 } 778 } 779 } 780 781 787 private String [] getUpdateColumnNames() 788 { 789 int size = updatableColumns.size(); 790 if (size == 0) 791 { 792 return (String [])null; 793 } 794 795 String [] names = new String [size]; 796 797 updatableColumns.copyInto(names); 798 799 return names; 800 } 801 802 public String getXML() 803 { 804 return null; 805 } 806 } 807 | Popular Tags |