public override void UnlockRoot(int lockKey) { // We unlock the reference table. // NOTE: This cause the reference table to unlock twice when we use the // 'MergeWithReference' method. While this isn't perfect behaviour, it // means if 'MergeWithReference' isn't used, we still maintain a safe // level of locking. ReferenceTable.UnlockRoot(lockKey); }
// ------ Public methods ------ ///<summary> /// Sets the whole reference table as a single group. ///</summary> public void SetWholeTableAsGroup() { wholeTableAsGroup = true; wholeTableGroupSize = ReferenceTable.RowCount; // Set up 'whole_table_group' to the list of all rows in the reference // table. IEnumerator <long> en = ReferenceTable.GetRowEnumerator(); wholeTableIsSimpleEnum = en is SimpleRowEnumerator; if (!wholeTableIsSimpleEnum) { wholeTableGroup = new List <long>((int)ReferenceTable.RowCount); while (en.MoveNext()) { wholeTableGroup.Add(en.Current); } } // Set up a group resolver for this method. groupResolver = new TableGroupResolver(this); }
///<summary> /// Returns a Table that is this function table merged with the cross /// reference table. ///</summary> ///<param name="maxColumn"></param> /// <remarks> /// The result table includes only one row from each group. /// <para> /// The 'max_column' argument is optional (can be null). If it's set to a /// column in the reference table, then the row with the max value from the /// group is used as the group row. For example, 'Part.id' will return the /// row with the maximum part.id from each group. /// </para> /// </remarks> ///<returns></returns> public Table MergeWithReference(ObjectName maxColumn) { Table table = ReferenceTable; IList <long> rowList; if (wholeTableAsGroup) { // Whole table is group, so take top entry of table. rowList = new List <long>(1); IEnumerator <long> rowEnum = table.GetRowEnumerator(); if (rowEnum.MoveNext()) { rowList.Add(rowEnum.Current); } else { // MAJOR HACK: If the referencing table has no elements then we choose // an arbitary index from the reference table to merge so we have // at least one element in the table. // This is to fix the 'SELECT COUNT(*) FROM empty_table' bug. rowList.Add(Int32.MaxValue - 1); } } else if (table.RowCount == 0) { rowList = new List <long>(0); } else if (groupLinks != null) { // If we are grouping, reduce down to only include one row from each // group. if (maxColumn == null) { rowList = GetTopFromEachGroup(); } else { int col_num = ReferenceTable.FindFieldName(maxColumn); rowList = GetMaxFromEachGroup(col_num); } } else { // OPTIMIZATION: This should be optimized. It should be fairly trivial // to generate a Table implementation that efficiently merges this // function table with the reference table. // This means there is no grouping, so merge with entire table, long rowCount = table.RowCount; rowList = new List <long>((int)rowCount); IEnumerator <long> en = table.GetRowEnumerator(); while (en.MoveNext()) { rowList.Add(en.Current); } } // Create a virtual table that's the new group table merged with the // functions in this... Table[] tabs = new Table[] { table, this }; IList <long>[] rowSets = new IList <long>[] { rowList, rowList }; VirtualTable outTable = new VirtualTable(tabs); outTable.Set(tabs, rowSets); table = outTable; return(table); }