/** * 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; }
/** * This overload variant of optimizeStatement is used by subclass CursorNode (as well as a minion * for the no-arg variant). * * @param offset Any OFFSET row count, or null * @param fetchFirst Any FETCH FIRST row count or null * @exception StandardException Thrown on error * @see DMLStatementNode#optimizeStatement() */ protected void optimizeStatement(ValueNode offset, ValueNode fetchFirst) throws StandardException { resultSet = resultSet.preprocess(getCompilerContext().getNumTables(), null, (FromList) null); resultSet = resultSet.optimize(getDataDictionary(), null, 1.0d); resultSet = resultSet.modifyAccessPaths(); // Any OFFSET/FETCH FIRST narrowing must be done *after* any rewrite of // the query tree (if not, underlying GROUP BY fails), but *before* the // final scroll insensitive result node set is added - that one needs // to sit on top - so now is the time. // // This example statement fails if we wrap *before* the optimization // above: // select max(a) from t1 group by b fetch first row only // // A java.sql.ResultSet#previous on a scrollable result set will fail // if we don't wrap *after* the ScrollInsensitiveResultSetNode below. // // We need only wrap the RowCountNode set if at least one of the // clauses is present. if (offset != null || fetchFirst != null) { resultSet = wrapRowCountNode(resultSet, offset, fetchFirst); } /* If this is a cursor, then we * need to generate a new ResultSetNode to enable the scrolling * on top of the tree before modifying the access paths. */ if (this instanceof CursorNode) { ResultColumnList siRCList; ResultColumnList childRCList; ResultSetNode siChild = resultSet; /* We get a shallow copy of the ResultColumnList and its * ResultColumns. (Copy maintains ResultColumn.expression for now.) */ siRCList = resultSet.getResultColumns(); childRCList = siRCList.copyListAndObjects(); resultSet.setResultColumns(childRCList); /* Replace ResultColumn.expression with new VirtualColumnNodes * in the ScrollInsensitiveResultSetNode's ResultColumnList. (VirtualColumnNodes include * pointers to source ResultSetNode, this, and source ResultColumn.) */ siRCList.genVirtualColumnNodes(resultSet, childRCList); /* Finally, we create the new ScrollInsensitiveResultSetNode */ resultSet = (ResultSetNode) getNodeFactory() .getNode( C_NodeTypes.SCROLL_INSENSITIVE_RESULT_SET_NODE, resultSet, siRCList, null, getContextManager()); // Propagate the referenced table map if it's already been created if (siChild.getReferencedTableMap() != null) { resultSet.setReferencedTableMap((JBitSet) siChild.getReferencedTableMap().clone()); } } }