private void pushOrderingDown(ResultSetNode rsn) throws StandardException { ContextManager cm = getContextManager(); NodeFactory nf = getNodeFactory(); OrderByList orderByList = (OrderByList) nf.getNode(C_NodeTypes.ORDER_BY_LIST, cm); for (int i = 0; i < intermediateOrderByColumns.length; i++) { OrderByColumn orderByColumn = (OrderByColumn) nf.getNode( C_NodeTypes.ORDER_BY_COLUMN, nf.getNode( C_NodeTypes.INT_CONSTANT_NODE, ReuseFactory.getInteger(intermediateOrderByColumns[i] + 1), cm), cm); if (intermediateOrderByDirection[i] < 0) orderByColumn.setDescending(); if (intermediateOrderByNullsLow[i]) orderByColumn.setNullsOrderedLow(); orderByList.addOrderByColumn(orderByColumn); } orderByList.bindOrderByColumns(rsn); rsn.pushOrderByList(orderByList); } // end of pushOrderingDown
/** * 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 { // Push the order by list down to the ResultSet if (orderByList != null) { // If we have more than 1 ORDERBY columns, we may be able to // remove duplicate columns, e.g., "ORDER BY 1, 1, 2". if (orderByList.size() > 1) { orderByList.removeDupColumns(); } subquery.pushOrderByList(orderByList); orderByList = null; } subquery.pushOffsetFetchFirst(offset, fetchFirst, hasJDBClimitClause); /* 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 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); }