📄 currentofnode.java
字号:
if(columnsTableName != null) if(columnsTableName.getSchemaName() == null && correlationName == null) columnsTableName.bind(this.getDataDictionary()); if (SanityManager.DEBUG) { SanityManager.ASSERT(preStmt!=null, "must have prepared statement"); } /* * We use the base table name of the target table. * This is necessary since we will be comparing with the table in * the delete or update statement which doesn't have a correlation * name. The select for which this column is created might have a * correlation name and so we won't find it if we look for exposed names * We shouldn't have to worry about multiple table since there should be * only one table. Beetle 4419 */ if (SanityManager.DEBUG) { SanityManager.ASSERT(baseTableName!=null,"no name on target table"); } if(baseTableName != null) if(baseTableName.getSchemaName() == null && correlationName == null) baseTableName.bind(this.getDataDictionary()); /* * If the column did not specify a name, or the specified name * matches the table we're looking at, see whether the column * is in this table, and also whether it is in the for update list. */ if (columnsTableName == null || columnsTableName.getFullTableName().equals(baseTableName.getFullTableName())) { boolean notfound = false; resultColumn = resultColumns.getResultColumn(columnReference.getColumnName()); if (resultColumn != null) { // If we found the ResultColumn, set the ColumnReference's // table number accordingly. Note: we used to only set // the tableNumber for correlated references (as part of // changes for DERBY-171) but inspection of code (esp. // the comments in FromList.bindColumnReferences() and // the getMatchingColumn() methods on other FromTables) // suggests that we should always set the table number // if we've found the ResultColumn. So we do that here. columnReference.setTableNumber( tableNumber ); // If there is a result column, are we really updating it? // If so, verify that the column is updatable as well notfound = (resultColumn.updatableByCursor() && !foundString( preStmt.getUpdateColumns(), columnReference.getColumnName())); } else { notfound = true; } if (notfound) { String printableString = (cursorName == null) ? "" : cursorName; throw StandardException.newException(SQLState.LANG_COLUMN_NOT_UPDATABLE_IN_CURSOR, columnReference.getColumnName(), printableString); } } return resultColumn; } /** * Preprocess a CurrentOfNode. For a CurrentOfNode, this simply means allocating * a referenced table map to avoid downstream NullPointerExceptions. * NOTE: There are no bits set in the referenced table map. * * @param numTables The number of tables in the DML Statement * @param gbl The group by list, if any * @param fromList The from list, if any * * @return ResultSetNode at top of preprocessed tree. * * @exception StandardException Thrown on error */ public ResultSetNode preprocess(int numTables, GroupByList gbl, FromList fromList) throws StandardException { /* Generate an empty referenced table map */ referencedTableMap = new JBitSet(numTables); return this; } /** * Optimize this CurrentOfNode. Nothing to do. * * @param dataDictionary The DataDictionary to use for optimization * @param predicate The predicate to optimize. This should * be a single-table predicate with the table * the same as the table in this FromTable. * @param predicateList The PredicateList to optimize. This should * be a single-table predicate with the table * the same as the table in this FromTable. * @param outerRows The number of outer joining rows * * @return ResultSetNode The top of the optimized subtree. * * @exception StandardException Thrown on error */ public ResultSetNode optimize(DataDictionary dataDictionary, PredicateList predicateList, double outerRows) throws StandardException { /* Get an optimizer so we can get a cost */ Optimizer optimizer = getOptimizer( (FromList) getNodeFactory().getNode( C_NodeTypes.FROM_LIST, getNodeFactory().doJoinOrderOptimization(), this, getContextManager()), predicateList, dataDictionary, (RequiredRowOrdering) null); /* Assume there is no cost associated with fetching the current row */ bestCostEstimate = optimizer.newCostEstimate(); bestCostEstimate.setCost(0.0d, outerRows, outerRows); return this; } /** * Generation on a CurrentOfNode creates a scan on the * cursor, CurrentOfResultSet. * <p> * This routine will generate and return a call of the form: * <pre><verbatim> ResultSetFactory.getCurrentOfResultSet(cursorName) </verbatim></pre> * * @param acb The ActivationClassBuilder for the class being built * @param mb The execute() method to be built * * @return A compiled Expression that returns a ResultSet that * scans the table. * * @exception StandardException Thrown on error */ public void generate(ActivationClassBuilder acb, MethodBuilder mb) throws StandardException { if (SanityManager.DEBUG) SanityManager.ASSERT(!statementResultSet, "CurrentOfNode not expected to be statement node"); /* Get the next ResultSet #, so that we can number this ResultSetNode, its * ResultColumnList and ResultSet. */ assignResultSetNumber(); mb.pushThis(); // for the putField // The generated java returned by this method is the expression: // ResultSetFactory.getCurrentOfResultSet( // #cursorName(), this, resultSetNumber) acb.pushGetResultSetFactoryExpression(mb); mb.push(cursorName); acb.pushThisAsActivation(mb); mb.push(resultSetNumber); mb.push(preStmt.getObjectName()); mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, "getCurrentOfResultSet", ClassName.NoPutResultSet, 4); mb.cast(ClassName.CursorResultSet); // the current of scan generator is what we return /* This table is the target of an update or a delete, so we must * wrap the Expression up in an assignment expression before * returning. Delete or update use the field that is set * to calculate the CurrentRowLocation value. * NOTE - scanExpress is a ResultSet. We will need to cast it to the * appropriate subclass. * For example, for a DELETE, instead of returning a call to the * ResultSetFactory, we will generate and return: * this.SCANRESULTSET = (cast to appropriate ResultSet type) * The outer cast back to ResultSet is needed so that * we invoke the appropriate method in the call to the ResultSetFactory */ mb.putField((String) null, acb.getRowLocationScanResultSetName(), ClassName.CursorResultSet); mb.cast(ClassName.NoPutResultSet); // add a check at activation reset time to see if the cursor has // changed underneath us. Doing it in the constructor allows the // compilation to happen MethodBuilder rmb = acb.startResetMethod(); rmb.pushThis(); rmb.push(cursorName); rmb.push(preStmt.getObjectName()); rmb.callMethod(VMOpcode.INVOKEVIRTUAL, ClassName.BaseActivation, "checkPositionedStatement", "void", 2); rmb.methodReturn(); rmb.complete(); } /** * Prints the sub-nodes of this object. See QueryTreeNode.java for * how tree printing is supposed to work. * * @param depth The depth of this node in the tree */ public void printSubNodes(int depth) { if (SanityManager.DEBUG) { super.printSubNodes(depth); printLabel(depth, "cursor: "); } } /** * Convert this object to a String. See comments in QueryTreeNode.java * for how this should be done for tree printing. * * @return This object as a String */ public String toString() { if (SanityManager.DEBUG) { return "preparedStatement: " + (preStmt == null? "no prepared statement yet\n" : preStmt.toString() + "\n")+ cursorName + "\n" + super.toString(); } else { return ""; } } // // class interface // public String getExposedName() { return exposedTableName.getFullTableName(); } public TableName getExposedTableName() { return exposedTableName; } public TableName getBaseCursorTargetTableName() { return baseTableName; } public String getCursorName() { return cursorName; } /** * Return the CursorNode associated with a positioned update/delete. * * @return CursorNode The associated CursorNode. * */ ExecPreparedStatement getCursorStatement() { Activation activation = getLanguageConnectionContext().lookupCursorActivation(cursorName); if (activation == null) return null; return activation.getPreparedStatement(); } /** * Get the lock mode for this table as the target of an update statement * (a delete or update). This is implemented only for base tables and * CurrentOfNodes. * * @see TransactionController * * @return The lock mode */ public int updateTargetLockMode() { /* Do row locking for positioned update/delete */ return TransactionController.MODE_RECORD; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -