public static ITable SimpleJoin(this ITable theTable, IQueryContext context, ITable table, ObjectName columnName, Operator op, Expression expression) { Table t = (Table)theTable; // Find the row with the name given in the condition. int lhsColumn = t.FindFieldName(columnName); if (lhsColumn == -1) { throw new Exception("Unable to find the LHS column specified in the condition: " + columnName); } // Create a variable resolver that can resolve columns in the destination // table. Table.TableVariableResolver resolver = ((Table)table).GetVariableResolver(); // The join algorithm. It steps through the RHS expression, selecting the // cells that match the relation from the LHS table (this table). List <long> thisRowSet = new List <long>(); List <long> tableRowSet = new List <long>(); IEnumerator <long> e = table.GetRowEnumerator(); while (e.MoveNext()) { long rowIndex = e.Current; resolver.SetId = (int)rowIndex; // Resolve expression into a constant. DataObject value = expression.Evaluate(resolver, context); // Select all the rows in this table that match the joining condition. IList <long> selectedSet = theTable.SelectRows(lhsColumn, op, value).ToList(); // Include in the set. int size = selectedSet.Count; for (int i = 0; i < size; ++i) { tableRowSet.Add(rowIndex); } thisRowSet.AddRange(selectedSet); } // Create the new VirtualTable with the joined tables. Table[] tabs = new Table[] { (Table)theTable, (Table)table }; IList <long>[] rowSets = new IList <long>[] { thisRowSet, tableRowSet }; VirtualTable outTable = new VirtualTable(tabs); outTable.Set(tabs, rowSets); return(outTable); }
/// <summary> /// Creates a grouping matrix for the given columns. /// </summary> /// <param name="columns"></param> /// <remarks> /// The grouping matrix is arranged so that each row of the refering /// table that is in the group is given a number that refers to the top /// group entry in the group list. The group list is a linked integer /// list that chains through each row item in the list. /// </remarks> public void CreateGroupMatrix(ObjectName[] columns) { // If we have zero rows, then don't bother creating the matrix. if (RowCount <= 0 || columns.Length <= 0) { return; } Table rootTable = ReferenceTable; long rowCount = rootTable.RowCount; int[] colLookup = new int[columns.Length]; for (int i = columns.Length - 1; i >= 0; --i) { colLookup[i] = rootTable.FindFieldName(columns[i]); } IList <long> rowList = rootTable.OrdereddRows(colLookup); // 'row_list' now contains rows in this table sorted by the columns to // group by. // This algorithm will generate two lists. The group_lookup list maps // from rows in this table to the group number the row belongs in. The // group number can be used as an index to the 'group_links' list that // contains consequtive links to each row in the group until -1 is reached // indicating the end of the group; groupLookup = new List <long>((int)rowCount); groupLinks = new List <long>((int)rowCount); int current_group = 0; long previous_row = -1; for (int i = 0; i < rowCount; ++i) { long rowIndex = rowList[i]; if (previous_row != -1) { bool equal = true; // Compare cell in column in this row with previous row. for (int n = 0; n < colLookup.Length && equal; ++n) { DataObject c1 = rootTable.GetValue(colLookup[n], rowIndex); DataObject c2 = rootTable.GetValue(colLookup[n], previous_row); equal = (c1.CompareTo(c2) == 0); } if (!equal) { // If end of group, set bit 15 groupLinks.Add(previous_row | 0x040000000); current_group = groupLinks.Count; } else { groupLinks.Add(previous_row); } } // groupLookup.Insert(row_index, current_group); PlaceAt(groupLookup, rowIndex, current_group); previous_row = rowIndex; } // Add the final row. groupLinks.Add(previous_row | 0x040000000); // Set up a group resolver for this method. groupResolver = new TableGroupResolver(this); }
/// <inheritdoc/> public override int FindFieldName(ObjectName v) { return(masterTable.FindFieldName(v)); }