📄 groupedaggregateresultset.java
字号:
/* Derby - Class org.apache.derby.impl.sql.execute.GroupedAggregateResultSet Copyright 1998, 2004 The Apache Software Foundation or its licensors, as applicable. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */package org.apache.derby.impl.sql.execute;import org.apache.derby.iapi.services.monitor.Monitor;import org.apache.derby.iapi.services.sanity.SanityManager;import org.apache.derby.iapi.services.stream.HeaderPrintWriter;import org.apache.derby.iapi.services.stream.InfoStreams;import org.apache.derby.iapi.services.io.Formatable;import org.apache.derby.iapi.sql.execute.CursorResultSet;import org.apache.derby.iapi.sql.Activation;import org.apache.derby.iapi.sql.ResultSet;import org.apache.derby.iapi.sql.execute.ExecRow;import org.apache.derby.iapi.sql.execute.ExecIndexRow;import org.apache.derby.iapi.sql.execute.NoPutResultSet;import org.apache.derby.iapi.store.access.ColumnOrdering;import org.apache.derby.iapi.types.DataValueDescriptor;import org.apache.derby.iapi.store.access.SortObserver;import org.apache.derby.iapi.store.access.TransactionController;import org.apache.derby.iapi.store.access.SortController;import org.apache.derby.iapi.store.access.ScanController;import org.apache.derby.iapi.services.loader.GeneratedMethod;import org.apache.derby.iapi.sql.execute.ExecutionFactory;import org.apache.derby.iapi.sql.execute.ExecutionContext;import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;import org.apache.derby.iapi.error.StandardException;import org.apache.derby.iapi.types.RowLocation;import org.apache.derby.iapi.services.io.FormatableArrayHolder;import java.util.Properties;import java.util.Vector;import java.util.Enumeration;/** * This ResultSet evaluates grouped, non distinct aggregates. * It will scan the entire source result set and calculate * the grouped aggregates when scanning the source during the * first call to next(). * * @author jerry (broken out from SortResultSet) */public class GroupedAggregateResultSet extends GenericAggregateResultSet implements CursorResultSet { /* Run time statistics variables */ public int rowsInput; public int rowsReturned; // set in constructor and not altered during // life of object. private ColumnOrdering[] order; private ExecIndexRow sortTemplateRow; public boolean hasDistinctAggregate; // true if distinct aggregate public boolean isInSortedOrder; // true if source results in sorted order private int maxRowSize; // set in open and not modified thereafter private ScanController scanController; // Cache ExecIndexRow private ExecIndexRow sourceExecIndexRow; private ExecIndexRow sortResultRow; // In order group bys private ExecIndexRow currSortedRow; private boolean nextCalled; // used to track and close sorts private long distinctAggSortId; private boolean dropDistinctAggSort; private long genericSortId; private boolean dropGenericSort; private TransactionController tc; // RTS public Properties sortProperties = new Properties(); /** * Constructor * * @param s input result set * @param isInSortedOrder true if the source results are in sorted order * @param aggregateItem indicates the number of the * SavedObject off of the PreparedStatement that holds the * AggregatorInfoList used by this routine. * @param orderingItem indicates the number of the * SavedObject off of the PreparedStatement that holds the * ColumOrdering array used by this routine * @param a activation * @param ra generated method to build an empty * output row * @param maxRowSize approx row size, passed to sorter * @param resultSetNumber The resultSetNumber for this result set * * @exception StandardException Thrown on error */ public GroupedAggregateResultSet(NoPutResultSet s, boolean isInSortedOrder, int aggregateItem, int orderingItem, Activation a, GeneratedMethod ra, int maxRowSize, int resultSetNumber, double optimizerEstimatedRowCount, double optimizerEstimatedCost, GeneratedMethod c) throws StandardException { super(s, aggregateItem, a, ra, resultSetNumber, optimizerEstimatedRowCount, optimizerEstimatedCost, c); this.isInSortedOrder = isInSortedOrder; sortTemplateRow = getExecutionFactory().getIndexableRow((ExecRow) rowAllocator.invoke(activation)); order = (ColumnOrdering[]) ((FormatableArrayHolder) (a.getPreparedStatement().getSavedObject(orderingItem))) .getArray(ColumnOrdering.class); if (SanityManager.DEBUG) { SanityManager.DEBUG("AggregateTrace","execution time: "+ a.getPreparedStatement().getSavedObject(aggregateItem)); } constructorTime += getElapsedMillis(beginTime); } /////////////////////////////////////////////////////////////////////////////// // // ResultSet interface (leftover from NoPutResultSet) // /////////////////////////////////////////////////////////////////////////////// /** * Open the scan. Load the sorter and prepare to get * rows from it. * * @exception StandardException thrown if cursor finished. */ public void openCore() throws StandardException { beginTime = getCurrentTimeMillis(); // REVISIT: through the direct DB API, this needs to be an // error, not an ASSERT; users can open twice. Only through JDBC // is access to open controlled and ensured valid. if (SanityManager.DEBUG) SanityManager.ASSERT( ! isOpen, "GroupedAggregateResultSet already open"); sortResultRow = getExecutionFactory().getIndexableRow(sortTemplateRow.getClone()); sourceExecIndexRow = getExecutionFactory().getIndexableRow(sortTemplateRow.getClone()); source.openCore(); /* If this is an in-order group by then we do not need the sorter. * (We can do the aggregation ourselves.) * We save a clone of the first row so that subsequent next()s * do not overwrite the saved row. */ if (isInSortedOrder) { currSortedRow = getNextRowFromRS(); if (currSortedRow != null) { currSortedRow = (ExecIndexRow) currSortedRow.getClone(); initializeVectorAggregation(currSortedRow); } } else { /* ** Load up the sorter */ scanController = loadSorter(); } isOpen = true; numOpens++; openTime += getElapsedMillis(beginTime); } /** * Load up the sorter. Feed it every row from the * source scan. If we have a vector aggregate, initialize * the aggregator for each source row. When done, close * the source scan and open the sort. Return the sort * scan controller. * * @exception StandardException thrown on failure. * * @return the sort controller */ private ScanController loadSorter() throws StandardException { SortController sorter; long sortId; ExecRow sourceRow; ExecRow inputRow; int inputRowCountEstimate = (int) optimizerEstimatedRowCount; boolean inOrder = isInSortedOrder; tc = getTransactionController(); ColumnOrdering[] currentOrdering = order; /* ** Do we have any distinct aggregates? If so, we'll need ** a separate sort. We use all of the sorting columns and ** drop the aggregation on the distinct column. Then ** we'll feed this into the sorter again w/o the distinct ** column in the ordering list. */ if (aggInfoList.hasDistinct()) { hasDistinctAggregate = true; GenericAggregator[] aggsNoDistinct = getSortAggregators(aggInfoList, true, activation.getLanguageConnectionContext(), source); SortObserver sortObserver = new AggregateSortObserver(true, aggsNoDistinct, aggregates, sortTemplateRow); sortId = tc.createSort((Properties)null, sortTemplateRow.getRowArray(), order, sortObserver, false, // not in order inputRowCountEstimate, // est rows, -1 means no idea maxRowSize // est rowsize ); sorter = tc.openSort(sortId); distinctAggSortId = sortId; dropDistinctAggSort = true; while ((sourceRow = source.getNextRowCore())!=null) { sorter.insert(sourceRow.getRowArray()); rowsInput++; } /* ** End the sort and open up the result set */ source.close(); sortProperties = sorter.getSortInfo().getAllSortInfo(sortProperties); sorter.close(); scanController = tc.openSortScan(sortId, activation.getResultSetHoldability()); /* ** Aggs are initialized and input rows ** are in order. All we have to do is ** another sort to remove (merge) the ** duplicates in the distinct column */ inOrder = true; inputRowCountEstimate = rowsInput; /* ** Drop the last column from the ordering. The ** last column is the distinct column. Don't ** pay any attention to the fact that the ordering ** object's name happens to correspond to a techo ** band from the 80's. ** ** If there aren't any ordering columns other ** than the distinct (i.e. for scalar distincts) ** just skip the 2nd sort altogether -- we'll ** do the aggregate merge ourselves rather than ** force a 2nd sort. */ if (order.length == 1) { return scanController; } ColumnOrdering[] newOrder = new ColumnOrdering[order.length - 1]; System.arraycopy(order, 0, newOrder, 0, order.length - 1); currentOrdering = newOrder; } SortObserver sortObserver = new AggregateSortObserver(true, aggregates, aggregates, sortTemplateRow); sortId = tc.createSort((Properties)null, sortTemplateRow.getRowArray(), currentOrdering, sortObserver, inOrder, inputRowCountEstimate, // est rows maxRowSize // est rowsize ); sorter = tc.openSort(sortId); genericSortId = sortId; dropGenericSort = true; /* The sorter is responsible for doing the cloning */ while ((inputRow = getNextRowFromRS()) != null) { sorter.insert(inputRow.getRowArray()); } source.close(); sortProperties = sorter.getSortInfo().getAllSortInfo(sortProperties); sorter.close(); return tc.openSortScan(sortId, activation.getResultSetHoldability()); } /** * Return the next row. * * @exception StandardException thrown on failure. * @exception StandardException ResultSetNotOpen thrown if not yet open. * * @return the next row in the result */ public ExecRow getNextRowCore() throws StandardException { if (!isOpen) { return null; } beginTime = getCurrentTimeMillis(); // In order group by if (isInSortedOrder) { // No rows, no work to do if (currSortedRow == null) { nextTime += getElapsedMillis(beginTime);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -