📄 fromsubquery.java
字号:
*/ if (resultColumn != null) { /* Is there a matching resultColumn in the subquery's RCL? */ resultColumn = subquery.getResultColumns().findParentResultColumn( resultColumn); if (resultColumn != null) { /* Is there a matching resultColumn in our RCL? */ resultColumn = resultColumns.findParentResultColumn( resultColumn); } } } else if ((generatedForHavingClause && ! generatedForGroupByClause) // 3 && (columnReference.getClause() != ValueNode.IN_SELECT_LIST) ) { resultColumn = null; } else if (generatedForGroupByClause) // 4 { resultColumn = resultColumns.getResultColumn( columnsTableName, columnReference.getColumnName()); } else if (columnsTableName == null || columnsTableName.equals(correlationName)) // 5? { resultColumn = resultColumns.getAtMostOneResultColumn(columnReference, correlationName); } if (resultColumn != null) { columnReference.setTableNumber(tableNumber); } return resultColumn; } /** * Preprocess a ResultSetNode - this currently means: * o Generating a referenced table map for each ResultSetNode. * o Putting the WHERE and HAVING clauses in conjunctive normal form (CNF). * o Converting the WHERE and HAVING clauses into PredicateLists and * classifying them. * o Ensuring that a ProjectRestrictNode is generated on top of every * FromBaseTable and generated in place of every FromSubquery. * o Pushing single table predicates down to the new ProjectRestrictNodes. * * @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 { /* We want to chop out the FromSubquery from the tree and replace it * with a ProjectRestrictNode. One complication is that there may be * ColumnReferences above us which point to the FromSubquery's RCL. * What we want to return is a tree with a PRN with the * FromSubquery's RCL on top. (In addition, we don't want to be * introducing any redundant ProjectRestrictNodes.) * Another complication is that we want to be able to only only push * projections and restrictions down to this ProjectRestrict, but * we want to be able to push them through as well. * So, we: * o call subquery.preprocess() which returns a tree with * a SelectNode or a RowResultSetNode on top. * o If the FSqry is flattenable(), then we return (so that the * caller can then call flatten()), otherwise we: * o generate a PRN, whose RCL is the FSqry's RCL, on top of the result. * o create a referencedTableMap for the PRN which represents * the FSqry's tableNumber, since ColumnReferences in the outer * query block would be referring to that one. * (This will allow us to push restrictions down to the PRN.) */ subquery = subquery.preprocess(numTables, gbl, fromList); /* Return if the FSqry is flattenable() * NOTE: We can't flatten a FromSubquery if there is a group by list * because the group by list must be ColumnReferences. For: * select c1 from v1 group by c1, * where v1 is select 1 from t1 * The expression under the last redundant ResultColumn is an IntConstantNode, * not a ColumnReference. * We also do not flatten a subquery if tableProperties is non-null, * as the user is specifying 1 or more properties for the derived table, * which could potentially be lost on the flattening. * RESOLVE - this is too restrictive. */ if ((gbl == null || gbl.size() == 0) && tableProperties == null && subquery.flattenableInFromSubquery(fromList)) { /* Set our table map to the subquery's table map. */ setReferencedTableMap(subquery.getReferencedTableMap()); return this; } return extractSubquery(numTables); } /** * Extract out and return the subquery, with a PRN on top. * (See FromSubquery.preprocess() for more details.) * * @param numTables The number of tables in the DML Statement * * @return ResultSetNode at top of extracted tree. * * @exception StandardException Thrown on error */ public ResultSetNode extractSubquery(int numTables) throws StandardException { JBitSet newJBS; ResultSetNode newPRN; newPRN = (ResultSetNode) getNodeFactory().getNode( C_NodeTypes.PROJECT_RESTRICT_NODE, subquery, /* Child ResultSet */ resultColumns, /* Projection */ null, /* Restriction */ null, /* Restriction as PredicateList */ null, /* Subquerys in Projection */ null, /* Subquerys in Restriction */ tableProperties, getContextManager() ); /* Set up the PRN's referencedTableMap */ newJBS = new JBitSet(numTables); newJBS.set(tableNumber); newPRN.setReferencedTableMap(newJBS); ((FromTable) newPRN).setTableNumber(tableNumber); return newPRN; } /** * Flatten this FSqry into the outer query block. The steps in * flattening are: * o Mark all ResultColumns as redundant, so that they are "skipped over" * at generate(). * o Append the wherePredicates to the outer list. * o Return the fromList so that the caller will merge the 2 lists * RESOLVE - FSqrys with subqueries are currently not flattenable. Some of * them can be flattened, however. We need to merge the subquery list when * we relax this restriction. * * NOTE: This method returns NULL when flattening RowResultSetNodes * (the node for a VALUES clause). The reason is that no reference * is left to the RowResultSetNode after flattening is done - the * expressions point directly to the ValueNodes in the RowResultSetNode's * ResultColumnList. * * @param rcl The RCL from the outer query * @param outerPList PredicateList to append wherePredicates to. * @param sql The SubqueryList from the outer query * @param gbl The group by list, if any * * @return FromList The fromList from the underlying SelectNode. * * @exception StandardException Thrown on error */ public FromList flatten(ResultColumnList rcl, PredicateList outerPList, SubqueryList sql, GroupByList gbl) throws StandardException { FromList fromList = null; SelectNode selectNode; resultColumns.setRedundant(); subquery.getResultColumns().setRedundant(); /* ** RESOLVE: Each type of result set should know how to remap itself. */ if (subquery instanceof SelectNode) { selectNode = (SelectNode) subquery; fromList = selectNode.getFromList(); // selectNode.getResultColumns().setRedundant(); if (selectNode.getWherePredicates().size() > 0) { outerPList.destructiveAppend(selectNode.getWherePredicates()); } if (selectNode.getWhereSubquerys().size() > 0) { sql.destructiveAppend(selectNode.getWhereSubquerys()); } } else if ( ! (subquery instanceof RowResultSetNode)) { if (SanityManager.DEBUG) { SanityManager.THROWASSERT("subquery expected to be either a SelectNode or a RowResultSetNode, but is a " + subquery.getClass().getName()); } } /* Remap all ColumnReferences from the outer query to this node. * (We replace those ColumnReferences with clones of the matching * expression in the SELECT's RCL. */ rcl.remapColumnReferencesToExpressions(); outerPList.remapColumnReferencesToExpressions(); if (gbl != null) { gbl.remapColumnReferencesToExpressions(); } return fromList; } /** * Get the exposed name for this table, which is the name that can * be used to refer to it in the rest of the query. * * @return The exposed name for this table. */ public String getExposedName() { return correlationName; } /** * Expand a "*" into a ResultColumnList with all of the * result columns from the subquery. * @exception StandardException Thrown on error */ public ResultColumnList getAllResultColumns(TableName allTableName) throws StandardException { ResultColumnList rcList = null; TableName exposedName; TableName toCompare; if(allTableName != null) toCompare = makeTableName(allTableName.getSchemaName(),correlationName); else toCompare = makeTableName(null,correlationName); if ( allTableName != null && ! allTableName.equals(toCompare)) { return null; } /* Cache exposed name for this table. * The exposed name becomes the qualifier for each column * in the expanded list. */ exposedName = makeTableName(null, correlationName); rcList = (ResultColumnList) getNodeFactory().getNode( C_NodeTypes.RESULT_COLUMN_LIST, getContextManager()); /* Build a new result column list based off of resultColumns. * NOTE: This method will capture any column renaming due to * a derived column list. */ int rclSize = resultColumns.size(); for (int index = 0; index < rclSize; index++) { ResultColumn resultColumn = (ResultColumn) resultColumns.elementAt(index); ValueNode valueNode; String columnName; if (resultColumn.isGenerated()) { continue; } // Build a ResultColumn/ColumnReference pair for the column // columnName = resultColumn.getName(); boolean isNameGenerated = resultColumn.isNameGenerated(); /* If this node was generated for a GROUP BY, then tablename for the CR, if any, * comes from the source RC. */ TableName tableName; if (correlationName == null && generatedForGroupByClause) { tableName = makeTableName(null, resultColumn.getTableName()); } else { tableName = exposedName; } valueNode = (ValueNode) getNodeFactory().getNode( C_NodeTypes.COLUMN_REFERENCE, columnName, tableName, getContextManager()); resultColumn = (ResultColumn) getNodeFactory().getNode( C_NodeTypes.RESULT_COLUMN, columnName, valueNode, getContextManager()); resultColumn.setNameGenerated(isNameGenerated); // Build the ResultColumnList to return // rcList.addResultColumn(resultColumn); } return rcList; } /** * Search to see if a query references the specifed table name. * * @param name Table name (String) to search for. * @param baseTable Whether or not name is for a base table * * @return true if found, else false * * @exception StandardException Thrown on error */ public boolean referencesTarget(String name, boolean baseTable) throws StandardException { return subquery.referencesTarget(name, baseTable); } /** * Return true if the node references SESSION schema tables (temporary or permanent) * * @return true if references SESSION schema tables, else false * * @exception StandardException Thrown on error */ public boolean referencesSessionSchema() throws StandardException { return subquery.referencesSessionSchema(); } /** * Bind any untyped null nodes to the types in the given ResultColumnList. * * @param bindingRCL The ResultColumnList with the types to bind to. * * @exception StandardException Thrown on error */ public void bindUntypedNullsToResultColumns(ResultColumnList bindingRCL) throws StandardException { subquery.bindUntypedNullsToResultColumns(bindingRCL); } /** * Decrement (query block) level (0-based) for this FromTable. * This is useful when flattening a subquery. * * @param decrement The amount to decrement by. */ void decrementLevel(int decrement) { super.decrementLevel(decrement); subquery.decrementLevel(decrement); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -