📄 hashscanresultset.java
字号:
/* Derby - Class org.apache.derby.impl.sql.execute.HashScanResultSet 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.loader.GeneratedMethod;import org.apache.derby.iapi.services.monitor.Monitor;import org.apache.derby.iapi.services.sanity.SanityManager;import org.apache.derby.iapi.services.io.Storable;import org.apache.derby.iapi.services.stream.HeaderPrintWriter;import org.apache.derby.iapi.services.stream.InfoStreams;import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;import org.apache.derby.iapi.error.StandardException;import org.apache.derby.iapi.services.i18n.MessageService;import org.apache.derby.iapi.reference.SQLState;import org.apache.derby.iapi.sql.execute.CursorResultSet;import org.apache.derby.iapi.sql.execute.ExecIndexRow;import org.apache.derby.iapi.sql.execute.ExecRow;import org.apache.derby.iapi.sql.execute.ExecutionContext;import org.apache.derby.iapi.sql.execute.NoPutResultSet;import org.apache.derby.iapi.sql.Activation;import org.apache.derby.iapi.sql.ResultSet;import org.apache.derby.iapi.store.access.ConglomerateController;import org.apache.derby.iapi.store.access.Qualifier;import org.apache.derby.iapi.store.access.RowUtil;import org.apache.derby.iapi.store.access.ScanController;import org.apache.derby.iapi.store.access.StaticCompiledOpenConglomInfo;import org.apache.derby.iapi.store.access.TransactionController;import org.apache.derby.iapi.types.DataValueDescriptor;import org.apache.derby.iapi.types.Orderable;import org.apache.derby.iapi.types.RowLocation;import org.apache.derby.iapi.store.access.BackingStoreHashtable;import org.apache.derby.iapi.services.io.FormatableBitSet;import org.apache.derby.iapi.services.io.FormatableArrayHolder;import org.apache.derby.iapi.services.io.FormatableIntHolder;import org.apache.derby.iapi.store.access.KeyHasher;import java.util.Enumeration;import java.util.Properties;import java.util.Vector;/** * Takes a conglomerate and a table filter builds a hash table on the * specified column of the conglomerate on the 1st open. Look up into the * hash table is done on the hash key column. The hash table consists of * either DataValueDescriptor[]s or Vectors of DataValueDescriptor[]. The store builds * the hash table. When a collision occurs, the store builds a Vector with * the colliding DataValueDescriptor[]s. * * @author jerry */public class HashScanResultSet extends NoPutResultSetImpl implements CursorResultSet{ private boolean hashtableBuilt; private ExecIndexRow startPosition; private ExecIndexRow stopPosition; protected ExecRow candidate; // candidate row is sparse protected ExecRow compactRow; // Variable for managing next() logic on hash entry protected boolean firstNext = true; private int numFetchedOnNext; private int entryVectorSize; private Vector entryVector; // set in constructor and not altered during // life of object. private long conglomId; protected StaticCompiledOpenConglomInfo scoci; private GeneratedMethod resultRowAllocator; private GeneratedMethod startKeyGetter; private int startSearchOperator; private GeneratedMethod stopKeyGetter; private int stopSearchOperator; public Qualifier[][] scanQualifiers; public Qualifier[][] nextQualifiers; private int initialCapacity; private float loadFactor; private int maxCapacity; private GeneratedMethod closeCleanup; public String tableName; public String indexName; public boolean forUpdate; private boolean runTimeStatisticsOn; private FormatableBitSet accessedCols; public int isolationLevel; public int lockMode; public int[] keyColumns; private boolean sameStartStopPosition; private boolean skipNullKeyColumns; protected BackingStoreHashtable hashtable; protected boolean eliminateDuplicates; // set to true in DistinctScanResultSet // Run time statistics public Properties scanProperties; public String startPositionString; public String stopPositionString; public int hashtableSize; public boolean isConstraint; public static final int DEFAULT_INITIAL_CAPACITY = -1; public static final float DEFAULT_LOADFACTOR = (float) -1.0; public static final int DEFAULT_MAX_CAPACITY = -1; // // class interface // public HashScanResultSet(long conglomId, StaticCompiledOpenConglomInfo scoci, Activation activation, GeneratedMethod resultRowAllocator, int resultSetNumber, GeneratedMethod startKeyGetter, int startSearchOperator, GeneratedMethod stopKeyGetter, int stopSearchOperator, boolean sameStartStopPosition, Qualifier[][] scanQualifiers, Qualifier[][] nextQualifiers, int initialCapacity, float loadFactor, int maxCapacity, int hashKeyItem, String tableName, String indexName, boolean isConstraint, boolean forUpdate, int colRefItem, int lockMode, boolean tableLocked, int isolationLevel, boolean skipNullKeyColumns, double optimizerEstimatedRowCount, double optimizerEstimatedCost, GeneratedMethod closeCleanup) throws StandardException { super(activation, resultSetNumber, optimizerEstimatedRowCount, optimizerEstimatedCost); this.scoci = scoci; this.conglomId = conglomId; if (SanityManager.DEBUG) { SanityManager.ASSERT( activation!=null, "hash scan must get activation context"); SanityManager.ASSERT( resultRowAllocator!= null, "hash scan must get row allocator"); if (sameStartStopPosition) { SanityManager.ASSERT(stopKeyGetter == null, "stopKeyGetter expected to be null when sameStartStopPosition is true"); } } this.resultRowAllocator = resultRowAllocator; this.startKeyGetter = startKeyGetter; this.startSearchOperator = startSearchOperator; this.stopKeyGetter = stopKeyGetter; this.stopSearchOperator = stopSearchOperator; this.sameStartStopPosition = sameStartStopPosition; this.scanQualifiers = scanQualifiers; this.nextQualifiers = nextQualifiers; this.initialCapacity = initialCapacity; this.loadFactor = loadFactor; this.maxCapacity = maxCapacity; this.tableName = tableName; this.indexName = indexName; this.isConstraint = isConstraint; this.forUpdate = forUpdate; this.skipNullKeyColumns = skipNullKeyColumns; /* Retrieve the hash key columns */ FormatableArrayHolder fah = (FormatableArrayHolder) (activation.getPreparedStatement(). getSavedObject(hashKeyItem)); FormatableIntHolder[] fihArray = (FormatableIntHolder[]) fah.getArray(FormatableIntHolder.class); keyColumns = new int[fihArray.length]; for (int index = 0; index < fihArray.length; index++) { keyColumns[index] = fihArray[index].getInt(); } // retrieve the valid column list from // the saved objects, if it exists this.accessedCols = null; if (colRefItem != -1) { this.accessedCols = (FormatableBitSet)(activation.getPreparedStatement(). getSavedObject(colRefItem)); } this.lockMode = lockMode; /* Isolation level - translate from language to store */ // If not specified, get current isolation level if (isolationLevel == ExecutionContext.UNSPECIFIED_ISOLATION_LEVEL) { isolationLevel = lcc.getCurrentIsolationLevel(); } if (isolationLevel == ExecutionContext.SERIALIZABLE_ISOLATION_LEVEL) { this.isolationLevel = TransactionController.ISOLATION_SERIALIZABLE; } else { /* NOTE: always do row locking on READ COMMITTED/UNCOMMITTED * and repeatable read scans unless the table is marked as * table locked (in sys.systables). * * We always get instantaneous locks as we will complete * the scan before returning any rows and we will fully * requalify the row if we need to go to the heap on a next(). */ if (! tableLocked) { this.lockMode = TransactionController.MODE_RECORD; } if (isolationLevel == ExecutionContext.READ_COMMITTED_ISOLATION_LEVEL) { this.isolationLevel = TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK; } else if (isolationLevel == ExecutionContext.READ_UNCOMMITTED_ISOLATION_LEVEL) { this.isolationLevel = TransactionController.ISOLATION_READ_UNCOMMITTED; } else if (isolationLevel == ExecutionContext.REPEATABLE_READ_ISOLATION_LEVEL) { this.isolationLevel = TransactionController.ISOLATION_REPEATABLE_READ; } } if (SanityManager.DEBUG) { SanityManager.ASSERT( ((isolationLevel == ExecutionContext.READ_COMMITTED_ISOLATION_LEVEL) || (isolationLevel == ExecutionContext.READ_UNCOMMITTED_ISOLATION_LEVEL) || (isolationLevel == ExecutionContext.REPEATABLE_READ_ISOLATION_LEVEL) || (isolationLevel == ExecutionContext.SERIALIZABLE_ISOLATION_LEVEL)), "Invalid isolation level - " + isolationLevel); } this.closeCleanup = closeCleanup; runTimeStatisticsOn = getLanguageConnectionContext().getRunTimeStatisticsMode(); /* Only call row allocators once */ candidate = (ExecRow) resultRowAllocator.invoke(activation); compactRow = getCompactRow(candidate, accessedCols, (FormatableBitSet) null, false); constructorTime += getElapsedMillis(beginTime); } // // ResultSet interface (leftover from NoPutResultSet) // /** * open a scan on the table. scan parameters are evaluated * at each open, so there is probably some way of altering * their values... * * @exception StandardException thrown on failure to open */ public void openCore() throws StandardException { TransactionController tc; beginTime = getCurrentTimeMillis(); if (SanityManager.DEBUG) SanityManager.ASSERT( ! isOpen, "HashScanResultSet already open"); // Get the current transaction controller tc = activation.getTransactionController(); if (startKeyGetter != null) { startPosition = (ExecIndexRow) startKeyGetter.invoke(activation); if (sameStartStopPosition) { stopPosition = startPosition; } } if (stopKeyGetter != null) { stopPosition = (ExecIndexRow) stopKeyGetter.invoke(activation); } // Check whether there are any comparisons with unordered nulls // on either the start or stop position. If there are, we can // (and must) skip the scan, because no rows can qualify if (skipScan(startPosition, stopPosition)) { // Do nothing ; } else if (! hashtableBuilt) { DataValueDescriptor[] startPositionRow = startPosition == null ? null : startPosition.getRowArray(); DataValueDescriptor[] stopPositionRow = stopPosition == null ? null : stopPosition.getRowArray(); hashtable = tc.createBackingStoreHashtableFromScan( conglomId, // conglomerate to open (forUpdate ? TransactionController.OPENMODE_FORUPDATE : 0), lockMode, isolationLevel, accessedCols, startPositionRow, startSearchOperator, scanQualifiers, stopPositionRow, stopSearchOperator, -1, // no limit on total rows. keyColumns, eliminateDuplicates,// remove duplicates? -1, // RESOLVE - is there a row estimate? maxCapacity, initialCapacity, // in memory Hashtable initial capacity loadFactor, // in memory Hashtable load factor runTimeStatisticsOn, skipNullKeyColumns); if (runTimeStatisticsOn) { hashtableSize = hashtable.size(); if (scanProperties == null) { scanProperties = new Properties(); } try { if (hashtable != null) { hashtable.getAllRuntimeStats(scanProperties); } } catch(StandardException se) { // ignore } } /* Remember that we created the hash table */ hashtableBuilt = true; /* ** Tell the activation about the number of qualifying rows. ** Do this only here, not in reopen, because we don't want ** to do this costly operation too often. */ activation.informOfRowCount(this, (long) hashtableSize); } isOpen = true; resetProbeVariables(); numOpens++; openTime += getElapsedMillis(beginTime); } /** * reopen this ResultSet. * * @exception StandardException thrown if cursor finished. */ public void reopenCore() throws StandardException { TransactionController tc; if (SanityManager.DEBUG) { SanityManager.ASSERT(isOpen, "HashScanResultSet already open"); } beginTime = getCurrentTimeMillis(); resetProbeVariables(); numOpens++; openTime += getElapsedMillis(beginTime); } private void resetProbeVariables() throws StandardException { firstNext = true; numFetchedOnNext = 0; entryVector = null; entryVectorSize = 0; if (nextQualifiers != null) { clearOrderableCache(nextQualifiers);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -