/// <summary>
                /// Copy constructor for an IndexLookupRecord.
                /// </summary>
                /// <param name="record">
                /// The record to copy.
                /// </param>
                public IndexLookupRecord(IIndexLookupRecord record)
                {
                    IndexLookupRecord thatRecord = (IndexLookupRecord)record;

                    m_sExtractor      = thatRecord.ExtractorDescription;
                    m_sIndex          = thatRecord.IndexDescription;
                    m_fOrdered        = thatRecord.IsOrdered;
                    m_cBytes          = thatRecord.MemoryUsage;
                    m_cDistinctValues = thatRecord.Size;
                    m_sIndexDef       = thatRecord.IndexDef;
                }
                /// <summary>
                /// Checks two cache entries for equality.
                /// </summary>
                /// <param name="obj">
                /// The <b>IndexLookupRecord</b> to compare to.
                /// </param>
                /// <returns>
                /// <b>true</b> if this <b>IndexLookupRecord</b> and the passed object are
                /// equivalent.
                /// </returns>
                public override bool Equals(object obj)
                {
                    if (this == obj)
                    {
                        return(true);
                    }

                    // Note: IndexLookupRecords are considered equivalent based on
                    //       the definition of the indices and not varying factors
                    //       such as index footprint and size.
                    IndexLookupRecord that = obj as IndexLookupRecord;

                    return(that != null &&
                           m_fOrdered == that.m_fOrdered &&
                           Equals(m_sIndexDef, that.m_sIndexDef) &&
                           m_sExtractor.Equals(that.m_sExtractor));
                }
                /// <summary>
                /// Merge the given step with this one.  This method assumes that
                /// the given step matches with this one.
                /// </summary>
                /// <param name="step">
                /// The <b>IStep</b> to merge.
                /// </param>
                public void Merge(IStep step)
                {
                    m_nSizeIn     += step.PreFilterKeySetSize;
                    m_nSizeOut    += step.PostFilterKeySetSize;
                    m_nEfficiency += step.Efficiency;
                    m_cMillis     += step.Duration;

                    IDictionary <IndexLookupRecord, IndexLookupRecord> dictIndexRecords =
                        new Dictionary <IndexLookupRecord, IndexLookupRecord>();

                    foreach (IndexLookupRecord record in step.IndexLookupRecords)
                    {
                        dictIndexRecords.Add(record, record);
                    }

                    foreach (IndexLookupRecord indexLookupRecord in m_setIndexLookupRecords)
                    {
                        IndexLookupRecord record = dictIndexRecords[indexLookupRecord];

                        if (record != null && record.IndexDescription != null)
                        {
                            indexLookupRecord.MemoryUsage     += record.MemoryUsage;
                            indexLookupRecord.Size             = Math.Max(indexLookupRecord.Size, record.Size);
                            indexLookupRecord.IndexDescription = indexLookupRecord.BuildIndexDescription();
                        }
                    }

                    IList listSteps = step.Steps;

                    int i = 0;

                    foreach (Step subStep in m_listSubSteps)
                    {
                        subStep.Merge((IStep)listSteps[i++]);
                    }
                }