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);
                }
            }
        }
Beispiel #4
0
        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();
        }