public CollationIndexResolver(ITable table, IndexCollation collation) { this.table = table; // Resolve the column names in the table into index references int sz = collation.Columns.Length; columns = new int[sz]; TableName tname = table.Name; for (int i = 0; i < sz; ++i) { string colName = collation.Columns[i].ColumnName; int colOffset = table.Columns.IndexOf(colName); if (colOffset == -1) throw new ApplicationException("Column '" + colName + "' not found."); columns[i] = colOffset; } // TODO: handle function indexes }
public SystemIndexSetDataSource CreateIndex(TableName onTable, string indexName, string indexType, IndexCollation collation) { CheckNotDisposed(); // Check the table name given is qualified CheckTableNameQualified(onTable); // We can't create an index that already exists if (IndexExists(onTable, indexName)) { throw new ApplicationException("Index '" + indexName + "' already exists"); } string[] columnNames = new string[collation.Columns.Length]; bool[] columnOrders = new bool[columnNames.Length]; for (int i = 0; i < columnNames.Length; i++) { columnNames[i] = collation.Columns[i].ColumnName; columnOrders[i] = collation.Columns[i].Ascending; } ITableIndex index = state.CreateIndex(new IndexName(onTable, indexName), indexType, columnNames, columnOrders); if (index == null) throw new ApplicationException("Unable to create index."); long indexId = state.CreateUniqueId(SystemTableNames.Index); // Create the index object SystemIndexSetDataSource indexSet = new SystemIndexSetDataSource(this, index); // Add this index item AddIndex(indexId, onTable, indexName, indexType, collation); // Log the change in the journal journal.AddEntry(JournalCommandCode.IndexAdd, indexId); OnChanged(); // Put it in the local cache indexMap[indexId] = indexSet; // Return the index return indexSet; }
internal void AddIndex(long indexId, TableName onTable, string indexName, string type, IndexCollation collation) { IMutableTable indexTable = GetTable(SystemTableNames.Index); TableRow row = indexTable.NewRow(); row.SetValue(0, indexId); row.SetValue(1, onTable.Schema); row.SetValue(2, onTable.Name); row.SetValue(3, indexName); row.SetValue(4, type); row.SetValue(5, collation.Function); row.SetValue(6, collation.Type.ToString()); row.SetValue(7, user.Name); indexTable.Insert(row); indexTable.Commit(); RowId insertRowId = row.Id; IMutableTable indexColumnTable = GetTable(SystemTableNames.ColumnSet); for (int i = 0; i < collation.Columns.Length; i++) { CollationColumn column = collation.Columns[i]; row = indexColumnTable.NewRow(); row.SetValue(0, indexId); row.SetValue(1, onTable.Schema); row.SetValue(2, onTable.Name); row.SetValue(3, indexName); row.SetValue(4, i); row.SetValue(5, column.ColumnName); row.SetValue(6, column.Ascending); indexColumnTable.Insert(row); } indexColumnTable.Commit(); // If this isn't an index on the INDEXES or TABLES tables,);););); if (!onTable.Equals(SystemTableNames.Tables) && !onTable.Equals(SystemTableNames.Index)) { // Update the indexes IIndexSetDataSource[] idxs = GetTableIndexes(SystemTableNames.Index); foreach (IIndexSetDataSource i in idxs) { i.Insert(insertRowId); } } }
public void PerformSample(SystemTransaction transaction) { // Translate into tables and column names ITable tableSource = transaction.GetTable(var.TableName); // DOn't bother unless the table has 64 or more values if (tableSource.RowCount < (DivisionPointCount * 2)) { sampleCount = 0; totalSize = 0; return; } // The number of elements in total totalSize = tableSource.RowCount; // The actual number of samples, sampleCount = (int)System.Math.Min(tableSource.RowCount / 2, MaxSampleCount); String col_name = var.Name; int colId = tableSource.Columns.IndexOf(var.Name); // Work out the size long size = tableSource.RowCount; // The sample point difference double sampleDiff = (double)size / sampleCount; // The index of the tables used in sampling IIndex<RowId> sampleIndex = transaction.CreateTemporaryIndex<RowId>(sampleCount); // Create a RowIndexCollation for this SqlType type; type = tableSource.Columns[colId].Type; IndexCollation collation = new IndexCollation(type, col_name); // Create the collation object, CollationIndexResolver resolver = new CollationIndexResolver(tableSource, collation); // The row cursor IRowCursor rowCursor = tableSource.GetRowCursor(); RowId[] sampleRowset = new RowId[sampleCount]; // First read in the row_ids we are sampling, { // The current sample point double p = 0; // The number read, int samplesRead = 0; // Make a sorted sample index of the dataset while (samplesRead < sampleCount) { long pos = ((long)p) - 1; pos = System.Math.Min(pos, tableSource.RowCount - 2); rowCursor.MoveTo(pos); if (!rowCursor.MoveNext()) throw new SystemException(); RowId rowId = rowCursor.Current; sampleRowset[samplesRead] = rowId; // Should this be Math.random(sample_diff * 2) for random distribution // of the samples? p += sampleDiff; ++samplesRead; } } // Now read the samples, { int samplePoint = 0; foreach (RowId rowId in sampleRowset) { // Hint ahead the samples we are picking, if ((samplePoint % 24) == 0) { for (int i = samplePoint; i < samplePoint + 24 && i < sampleRowset.Length; ++i) { tableSource.PrefetchValue(-1, sampleRowset[i]); } } // Pick the sample and sort it, SqlObject[] sample = new SqlObject[] { tableSource.GetValue(colId, rowId) }; sampleIndex.Insert(sample, rowId, resolver); ++samplePoint; } } // Now extract the interesting sample points from the sorted set IIndexCursor<RowId> samplesCursor = sampleIndex.GetCursor(); long sampleIndexSize = sampleIndex.Count; double divisionDiff = sampleIndexSize / (DivisionPointCount - 1); for (int i = 0; i < DivisionPointCount; ++i) { long samplePoint = (long)(divisionDiff * i); if (samplePoint >= sampleIndexSize) { samplePoint = sampleIndexSize - 1; } samplesCursor.Position = samplePoint - 1; if (!samplesCursor.MoveNext()) throw new SystemException(); RowId rowId = samplesCursor.Current; divisionPoints[i] = tableSource.GetValue(colId, rowId); } // Clear the temporary index sampleIndex.Clear(); }