📄 resultsetnode.java
字号:
/** * Evaluate whether or not the subquery in a FromSubquery is flattenable. * Currently, a FSqry is flattenable if all of the following are true: * o Subquery is a SelectNode. (ie, not a RowResultSetNode or a UnionNode) * o It contains no top level subqueries. (RESOLVE - we can relax this) * o It does not contain a group by or having clause * o It does not contain aggregates. * * @param fromList The outer from list * * @return boolean Whether or not the FromSubquery is flattenable. */ public boolean flattenableInFromSubquery(FromList fromList) { if (SanityManager.DEBUG) SanityManager.THROWASSERT( "flattenableInFromSubquery() not expected to be called for " + getClass().toString()); return false; } /** * Get a parent ProjectRestrictNode above us. * This is useful when we need to preserve the * user specified column order when reordering the * columns in the distinct when we combine * an order by with a distinct. * * @return A parent ProjectRestrictNode to do column reordering * * @exception StandardException Thrown on error */ ResultSetNode genProjectRestrictForReordering() throws StandardException { ResultColumnList prRCList; /* We get a shallow copy of the ResultColumnList and its * ResultColumns. (Copy maintains ResultColumn.expression for now.) */ prRCList = resultColumns; resultColumns = resultColumns.copyListAndObjects(); /* Replace ResultColumn.expression with new VirtualColumnNodes * in the ProjectRestrictNode's ResultColumnList. (VirtualColumnNodes include * pointers to source ResultSetNode, this, and source ResultColumn.) * NOTE: We don't want to mark the underlying RCs as referenced, otherwise * we won't be able to project out any of them. */ prRCList.genVirtualColumnNodes(this, resultColumns, false); /* Finally, we create the new ProjectRestrictNode */ return (ResultSetNode) getNodeFactory().getNode( C_NodeTypes.PROJECT_RESTRICT_NODE, this, prRCList, null, /* Restriction */ null, /* Restriction as PredicateList */ null, /* Project subquery list */ null, /* Restrict subquery list */ null, getContextManager() ); } /** * Optimize a ResultSetNode. This means choosing the best access * path for each table under the ResultSetNode, among other things. * * The only RSNs that need to implement their own optimize() are a * SelectNode and those RSNs that can appear above a SelectNode in the * query tree. Currently, a ProjectRestrictNode is the only RSN that * can appear above a SelectNode. * * @param dataDictionary The DataDictionary to use for optimization * @param predicateList The PredicateList to apply. * @param outerRows The number of outer joining rows * * @return ResultSetNode The top of the optimized query tree * * @exception StandardException Thrown on error */ public ResultSetNode optimize(DataDictionary dataDictionary, PredicateList predicates, double outerRows) throws StandardException { if (SanityManager.DEBUG) SanityManager.ASSERT(false, "optimize() is not expected to be called for " + this.getClass().toString()); return null; } /** * Modify the access paths according to the decisions the optimizer * made. This can include adding project/restrict nodes, * index-to-base-row nodes, etc. * * @return The modified query tree * * @exception StandardException Thrown on error */ public ResultSetNode modifyAccessPaths() throws StandardException { /* Default behavior is to do nothing */ return this; } /** * Modify the access paths according to the decisions the optimizer * made. This can include adding project/restrict nodes, * index-to-base-row nodes, etc. * * @param predList A list of optimizable predicates that should * be pushed to this ResultSetNode, as determined by optimizer. * @return The modified query tree * @exception StandardException Thrown on error */ public ResultSetNode modifyAccessPaths(PredicateList predList) throws StandardException { // Default behavior is to call the no-arg version of this method. return modifyAccessPaths(); } ResultColumnDescriptor[] makeResultDescriptors(ExecutionContext ec) { return resultColumns.makeResultDescriptors(ec); } /* ** Check whether the column lengths and types of the result columns ** match the expressions under those columns. This is useful for ** INSERT and UPDATE statements. For SELECT statements this method ** should always return true. There is no need to call this for a ** DELETE statement. ** ** @return true means all the columns match their expressions, ** false means at least one column does not match its ** expression */ boolean columnTypesAndLengthsMatch() throws StandardException { return resultColumns.columnTypesAndLengthsMatch(); } /** * Set the resultColumns in this ResultSetNode * * @param resultColumns The new ResultColumnList for this ResultSetNode * * @return None. */ public void setResultColumns(ResultColumnList newRCL) { resultColumns = newRCL; } /** * Get the resultColumns for this ResultSetNode * * @return ResultColumnList for this ResultSetNode */ public ResultColumnList getResultColumns() { return resultColumns; } /** * Set the referencedTableMap in this ResultSetNode * * @param newRTM The new referencedTableMap for this ResultSetNode * * @return None. */ public void setReferencedTableMap(JBitSet newRTM) { referencedTableMap = newRTM; } /** * Get the referencedTableMap for this ResultSetNode * * @return JBitSet Referenced table map for this ResultSetNode */ public JBitSet getReferencedTableMap() { return referencedTableMap; } /** * Fill the referencedTableMap with this ResultSetNode. * * @param passedMap The table map to fill in. * * @return Nothing. */ public void fillInReferencedTableMap(JBitSet passedMap) { } /** * Check for (and reject) ? parameters directly under the ResultColumns. * This is done for SELECT statements. * * @return Nothing * * @exception StandardException Thrown if a ? parameter found * directly under a ResultColumn */ public void rejectParameters() throws StandardException { /* Okay if no resultColumns yet - means no parameters there */ if (resultColumns != null) { resultColumns.rejectParameters(); } } /** * Check for (and reject) XML values directly under the ResultColumns. * This is done for SELECT/VALUES statements. We reject values * in this case because JDBC does not define an XML type/binding * and thus there's no standard way to pass such a type back * to a JDBC application. * * @return Nothing * * @exception StandardException Thrown if an XML value found * directly under a ResultColumn */ public void rejectXMLValues() throws StandardException { if (resultColumns != null) { resultColumns.rejectXMLValues(); } } /** * Rename generated result column names as '1', '2' etc... These will be the result * column names seen by JDBC clients. */ public void renameGeneratedResultNames() throws StandardException { for (int i=0; i<resultColumns.size(); i++) { ResultColumn rc = (ResultColumn) resultColumns.elementAt(i); if (rc.isNameGenerated()) rc.setName(Integer.toString(i+1)); } } /** This method is overridden to allow a resultset node to know if it is the one controlling the statement -- i.e., it is the outermost result set node for the statement. */ public void markStatementResultSet() { statementResultSet = true; } /** This utility method is used by result set nodes that can be statement nodes to determine what their final argument is; if they are the statement result set, and there is a current date/time request, then a method will have been generated. Otherwise, a simple null is passed in to the result set method. */ void closeMethodArgument(ExpressionClassBuilder acb, MethodBuilder mb) { /* For supporting current datetime, we may have a method that needs to be called when the statement's result set is closed. */ if (statementResultSet) { acb.pushResultSetClosedMethodFieldAccess(mb); } else { mb.pushNull(ClassName.GeneratedMethod); } } /** * This ResultSet is the source for an Insert. The target RCL * is in a different order and/or a superset of this RCL. In most cases * we will reorder and/or add defaults to the current RCL so that is * matches the target RCL. Those RSNs whose generate() method does * not handle projects will insert a PRN, with a new RCL which matches * the target RCL, above the current RSN. * NOTE - The new or enhanced RCL will be fully bound. * * @param numTargetColumns # of columns in target RCL * @param colMap[] int array representation of correspondence between * RCLs - colmap[i] = -1 -> missing in current RCL * colmap[i] = j -> targetRCL(i) <-> thisRCL(j+1) * @param dataDictionary DataDictionary to use * @param targetTD TableDescriptor for target if the target is not a VTI, null if a VTI * @param targetVTI Target description if it is a VTI, null if not a VTI * * @return ResultSetNode The new top of the tree * * @exception StandardException Thrown on error */ public ResultSetNode enhanceRCLForInsert(int numTargetColumns, int[] colMap, DataDictionary dataDictionary, TableDescriptor targetTD, FromVTI targetVTI) throws StandardException { // our newResultCols are put into the bound form straight away. ResultColumnList newResultCols = (ResultColumnList) getNodeFactory().getNode( C_NodeTypes.RESULT_COLUMN_LIST, getContextManager()); int numResultSetColumns = resultColumns.size(); /* Create a massaged version of the source RCL. * (Much simpler to build new list and then assign to source, * rather than massage the source list in place.) */ for (int index = 0; index < numTargetColumns; index++) { ResultColumn newResultColumn = null; ColumnReference newColumnReference; if (colMap[index] != -1) { // getResultColumn uses 1-based positioning, so offset the colMap entry appropriately newResultColumn = resultColumns.getResultColumn(colMap[index]+1); } else { newResultColumn = genNewRCForInsert(targetTD, targetVTI, index + 1, dataDictionary); } newResultCols.addResultColumn(newResultColumn); } /* Set the source RCL to the massaged version */ resultColumns = newResultCols; return this; } /** * Generate the RC/expression for an unspecified column in an insert. * Use the default if one exists. * * @param targetTD Target TableDescriptor if the target is not a VTI, null if a VTI. * @param targetVTI Target description if it is a VTI, null if not a VTI * @param columnNumber The column number * @param dataDictionary The DataDictionary * @return The RC/expression for the unspecified column. * * @exception StandardException Thrown on error */ ResultColumn genNewRCForInsert(TableDescriptor targetTD, FromVTI targetVTI, int columnNumber, DataDictionary dataDictionary) throws StandardException { ResultColumn newResultColumn = null; // the i-th column's value was not specified, so create an // expression containing its default value (null for now) // REVISIT: will we store trailing nulls? if( targetVTI != null) { newResultColumn = targetVTI.getResultColumns().getResultColumn( columnNumber); newResultColumn = newResultColumn.cloneMe(); newResultColumn.setExpressionToNullNode(); } else { // column position is 1-based, index is 0-based. ColumnDescriptor colDesc = targetTD.getColumnDescriptor(columnNumber); DataTypeDescriptor colType = colDesc.getType(); // Check for defaults DefaultInfoImpl defaultInfo = (DefaultInfoImpl) colDesc.getDefaultInfo(); //Column has constant default value , //if it have defaultInfo and not be autoincrement. if (defaultInfo != null && ! colDesc.isAutoincrement()) { //RESOLVEPARAMETER - skip the tree if we have the value
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -