📄 projectrestrictnode.java
字号:
if (mapArray[index] != index + 1) { break; } } if (index == mapArray.length) { doesProjection = false; } } /* Generate the ProjectRestrictSet: * arg1: childExpress - Expression for childResultSet * arg2: Activation * arg3: restrictExpress - Expression for restriction * arg4: projectExpress - Expression for projection * arg5: resultSetNumber * arg6: constantExpress - Expression for constant restriction * (for example, where 1 = 2) * arg7: mapArrayItem - item # for mapping of source columns * arg8: reuseResult - whether or not the result row can be reused * (ie, will it always be the same) * arg9: doesProjection - does this node do a projection * arg10: estimated row count * arg11: estimated cost * arg12: close method */ acb.pushGetResultSetFactoryExpression(mb); if (genChildResultSet) childResult.generateResultSet(acb, mb); else childResult.generate((ActivationClassBuilder)acb, mb); /* Get the next ResultSet #, so that we can number this ResultSetNode, its * ResultColumnList and ResultSet. */ assignResultSetNumber(); /* Set the point of attachment in all subqueries attached * to this node. */ if (projectSubquerys != null && projectSubquerys.size() > 0) { projectSubquerys.setPointOfAttachment(resultSetNumber); } if (restrictSubquerys != null && restrictSubquerys.size() > 0) { restrictSubquerys.setPointOfAttachment(resultSetNumber); } // Load our final cost estimate. costEstimate = getFinalCostEstimate(); acb.pushThisAsActivation(mb); // if there is no restriction, we just want to pass null. if (restriction == null) { mb.pushNull(ClassName.GeneratedMethod); } else { // this sets up the method and the static field. // generates: // Object userExprFun { } MethodBuilder userExprFun = acb.newUserExprFun(); // restriction knows it is returning its value; /* generates: * return <restriction.generate(acb)>; * and adds it to userExprFun * NOTE: The explicit cast to DataValueDescriptor is required * since the restriction may simply be a boolean column or subquery * which returns a boolean. For example: * where booleanColumn */ restriction.generateExpression(acb, userExprFun); userExprFun.methodReturn(); // we are done modifying userExprFun, complete it. userExprFun.complete(); // restriction is used in the final result set as an access of the new static // field holding a reference to this new method. // generates: // ActivationClass.userExprFun // which is the static field that "points" to the userExprFun // that evaluates the where clause. acb.pushMethodReference(mb, userExprFun); } /* Determine whether or not reflection is needed for the projection. * Reflection is not needed if all of the columns map directly to source * columns. */ if (reflectionNeededForProjection()) { // for the resultColumns, we generate a userExprFun // that creates a new row from expressions against // the current row of the child's result. // (Generate optimization: see if we can simply // return the current row -- we could, but don't, optimize // the function call out and have execution understand // that a null function pointer means take the current row // as-is, with the performance trade-off as discussed above.) /* Generate the Row function for the projection */ resultColumns.generateCore(acb, mb, false); } else { mb.pushNull(ClassName.GeneratedMethod); } mb.push(resultSetNumber); // if there is no constant restriction, we just want to pass null. if (constantRestriction == null) { mb.pushNull(ClassName.GeneratedMethod); } else { // this sets up the method and the static field. // generates: // userExprFun { } MethodBuilder userExprFun = acb.newUserExprFun(); // restriction knows it is returning its value; /* generates: * return <restriction.generate(acb)>; * and adds it to userExprFun * NOTE: The explicit cast to DataValueDescriptor is required * since the restriction may simply be a boolean column or subquery * which returns a boolean. For example: * where booleanColumn */ constantRestriction.generateExpression(acb, userExprFun); userExprFun.methodReturn(); // we are done modifying userExprFun, complete it. userExprFun.complete(); // restriction is used in the final result set as an access // of the new static field holding a reference to this new method. // generates: // ActivationClass.userExprFun // which is the static field that "points" to the userExprFun // that evaluates the where clause. acb.pushMethodReference(mb, userExprFun); } mb.push(mapArrayItem); mb.push(resultColumns.reusableResult()); mb.push(doesProjection); mb.push(costEstimate.rowCount()); mb.push(costEstimate.getEstimatedCost()); closeMethodArgument(acb, mb); mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, "getProjectRestrictResultSet", ClassName.NoPutResultSet, 12); } /** * Determine whether this ProjectRestrict does anything. If it doesn't * filter out any rows or columns, it's a No-Op. * * @return true if this ProjectRestrict is a No-Op. */ boolean nopProjectRestrict() { /* ** This ProjectRestrictNode is not a No-Op if it does any ** restriction. */ if ( (restriction != null) || (restrictionList != null && restrictionList.size() > 0) ) { return false; } ResultColumnList childColumns = childResult.getResultColumns(); ResultColumnList PRNColumns = this.getResultColumns(); /* ** The two lists have the same numbers of elements. Are the lists ** identical? In other words, is the expression in every ResultColumn ** in the PRN's RCL a ColumnReference that points to the same-numbered ** column? */ if (PRNColumns.nopProjection(childColumns)) return true; return false; } /** * Bypass the generation of this No-Op ProjectRestrict, and just generate * its child result set. * * @exception StandardException Thrown on error */ public void generateNOPProjectRestrict() throws StandardException { this.getResultColumns().setRedundant(); } /** * Consider materialization for this ResultSet tree if it is valid and cost effective * (It is not valid if incorrect results would be returned.) * * @return Top of the new/same ResultSet tree. * * @exception StandardException Thrown on error */ public ResultSetNode considerMaterialization(JBitSet outerTables) throws StandardException { childResult = childResult.considerMaterialization(outerTables); if (childResult.performMaterialization(outerTables)) { MaterializeResultSetNode mrsn; ResultColumnList prRCList; /* If the restriction contians a ColumnReference from another * table then the MRSN must go above the childResult. Otherwise we can put * it above ourselves. (The later is optimal since projection and restriction * will only happen once.) * Put MRSN above PRN if any of the following are true: * o PRN doesn't have a restriction list * o PRN's restriction list is empty * o Table's referenced in PRN's restriction list are a subset of * table's referenced in PRN's childResult. (NOTE: Rather than construct * a new, empty JBitSet before checking, we simply clone the childResult's * referencedTableMap. This is done for code simplicity and will not * affect the result.) */ ReferencedTablesVisitor rtv = new ReferencedTablesVisitor( (JBitSet) childResult.getReferencedTableMap().clone()); boolean emptyRestrictionList = (restrictionList == null || restrictionList.size() == 0); if (! emptyRestrictionList) { restrictionList.accept(rtv); } if (emptyRestrictionList || childResult.getReferencedTableMap().contains(rtv.getTableMap())) { /* We get a shallow copy of the ResultColumnList and its * ResultColumns. (Copy maintains ResultColumn.expression for now.) */ prRCList = resultColumns; setResultColumns(resultColumns.copyListAndObjects()); /* Replace ResultColumn.expression with new VirtualColumnNodes * in the NormalizeResultSetNode's ResultColumnList. (VirtualColumnNodes include * pointers to source ResultSetNode, this, and source ResultColumn.) */ prRCList.genVirtualColumnNodes(this, resultColumns); /* Finally, we create the new MaterializeResultSetNode */ mrsn = (MaterializeResultSetNode) getNodeFactory().getNode( C_NodeTypes.MATERIALIZE_RESULT_SET_NODE, this, prRCList, tableProperties, getContextManager()); // Propagate the referenced table map if it's already been created if (referencedTableMap != null) { mrsn.setReferencedTableMap((JBitSet) referencedTableMap.clone()); } return mrsn; } else { /* We get a shallow copy of the ResultColumnList and its * ResultColumns. (Copy maintains ResultColumn.expression for now.) */ prRCList = childResult.getResultColumns(); childResult.setResultColumns(prRCList.copyListAndObjects()); /* Replace ResultColumn.expression with new VirtualColumnNodes * in the MaterializeResultSetNode's ResultColumnList. (VirtualColumnNodes include * pointers to source ResultSetNode, this, and source ResultColumn.) */ prRCList.genVirtualColumnNodes(childResult, childResult.getResultColumns()); /* RESOLVE - we need to push single table predicates down so that * they get applied while building the MaterializeResultSet. */ /* Finally, we create the new MaterializeResultSetNode */ mrsn = (MaterializeResultSetNode) getNodeFactory().getNode( C_NodeTypes.MATERIALIZE_RESULT_SET_NODE, childResult, prRCList, tableProperties, getContextManager()); // Propagate the referenced table map if it's already been created if (childResult.getReferencedTableMap() != null) { mrsn.setReferencedTableMap((JBitSet) childResult.getReferencedTableMap().clone()); } childResult = mrsn; } } return this; } /** * Determine whether or not the specified name is an exposed name in * the current query block. * * @param name The specified name to search for as an exposed name. * @param schemaName Schema name, if non-null. * @param exactMatch Whether or not we need an exact match on specified schema and table * names or match on table id. * * @return The FromTable, if any, with the exposed name. * * @exception StandardException Thrown on error */ protected FromTable getFromTableByName(String name, String schemaName, boolean exactMatch) throws StandardException { return childResult.getFromTableByName(name, schemaName, exactMatch); } /** * Get the lock mode for the target of an update statement * (a delete or update). The update mode will always be row for * CurrentOfNodes. It will be table if there is no where clause. * * @return The lock mode */ public int updateTargetLockMode() { if (restriction != null || constantRestriction != null) { return TransactionController.MODE_RECORD; } else { return childResult.updateTargetLockMode(); } } /** * Is it possible to do a distinct scan on this ResultSet tree. * (See SelectNode for the criteria.) * * @param distinctColumns the set of distinct columns * @return Whether or not it is possible to do a distinct scan on this ResultSet tree. */ boolean isPossibleDistinctScan(Set distinctColumns) { if (restriction != null || (restrictionList != null && restrictionList.size() != 0)) { return false; } HashSet columns = new HashSet(); for (int i = 0; i < resultColumns.size(); i++) { ResultColumn rc = (ResultColumn) resultColumns.elementAt(i); BaseColumnNode bc = rc.getBaseColumnNode(); if (bc == null) return false; columns.add(bc); } return columns.equals(distinctColumns) && childResult.isPossibleDistinctScan(distinctColumns); } /** * Mark the underlying scan as a distinct scan. * * @return Nothing. */ void markForDistinctScan() { childResult.markForDistinctScan(); } /** * Accept a visitor, and call v.visit() * on child nodes as necessary. * * @param v the visitor * * @exception StandardException on error */ public Visitable accept(Visitor v) throws StandardException { if (v.skipChildren(this)) { return v.visit(this); } Visitable returnNode = super.accept(v); if (restriction != null && !v.stopTraversal()) { restriction = (ValueNode)restriction.accept(v); } if (restrictionList != null && !v.stopTraversal()) { restrictionList = (PredicateList)restrictionList.accept(v); } return returnNode; } /** * set the Information gathered from the parent table that is * required to peform a referential action on dependent table. * * @return Nothing. */ public void setRefActionInfo(long fkIndexConglomId, int[]fkColArray, String parentResultSetId, boolean dependentScan) { childResult.setRefActionInfo(fkIndexConglomId, fkColArray, parentResultSetId, dependentScan); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -