Example #1
0
 public ITable GetGroupValue(long rowid)
 {
     long n = (rowid * 2);
     // Get the group position and size in the index
     long groupPos = childGroupsIndex[n];
     long groupSize = childGroupsIndex[n + 1];
     // Create an interator over this subset of the filter index
     SubsetRowCursor subset = new SubsetRowCursor(BaseTable.GetRowCursor(), groupPos, groupSize);
     // Return the table subset
     SubsetTable groupTable = new SubsetTable(BaseTable, subset);
     // The subset retains the order of the child
     groupTable.SetOrderCompositeIsChild();
     // Return the group
     return groupTable;
 }
Example #2
0
        private ITable SortFilter(ITable table, FilterExpression expression)
        {
            // The filter operation which is a function that describes the sort terms
            Expression filterExp = expression.Filter;
            if (!(filterExp is FunctionExpression))
                throw new ArgumentException("Expected a function as argument to the filter.");

            ITable resultTable = table;

            // If there's something to sort,
            if (table.RowCount > 1) {
                // Get the composite function representing the sort collation,
                FunctionExpression compositeExp = (FunctionExpression) filterExp;
                if (!compositeExp.Name.Equals("composite"))
                    throw new ArgumentException("Invalid composite function for sorting.");

                // The natural ordering of the child
                Expression naturalChildOrder = GetTableOrderComposite(table);
                if (naturalChildOrder != null) {
                    if (naturalChildOrder.Equals(compositeExp))
                        // No sort necessary, already sorted
                        return table;

                    // TODO: test for the reverse condition, which we can optimize
                    //   with a reverse row iterator.
                }

                int paramCount = compositeExp.Parameters.Count;
                int termCount = paramCount / 2;
                IIndexSetDataSource rowIndex;
                bool naturalOrder = true;
                // If 1 sort term,
                if (termCount == 1) {
                    Expression sortExp = (Expression) compositeExp.Parameters[0];
                    naturalOrder = SqlObject.Equals((SqlObject)compositeExp.Parameters[1], SqlObject.True);
                    // Get the index candidate
                    string indexName = sortExp.IndexCandidate;
                    TableName indexTableName = sortExp.IndexTableName;
                    // Index available?
                    rowIndex = GetIndex(table, indexName);
                } else {
                    // Multiple terms,
                    // Get the index candidate if there is one
                    string indexName = compositeExp.IndexCandidate;
                    TableName indexTableame = compositeExp.IndexTableName;
                    // Index available?
                    rowIndex = GetIndex(table, indexName);
                }

                // If we have an index,
                if (rowIndex != null) {
                    IRowCursor sortedCursor = rowIndex.Select(SelectableRange.Full);
                    if (!naturalOrder)
                        // Reverse iterator,
                        sortedCursor = new ReverseRowCursor(sortedCursor);

                    SubsetTable sortedTable = new SubsetTable(table, sortedCursor);
                    sortedTable.IndexRequestFallthrough = true;
                    // Set the order composite function the describes how the subset is
                    // naturally sorted.
                    sortedTable.OrderComposite = (Expression) compositeExp.Clone();
                    resultTable = sortedTable;
                } else {
                    // NOTE: There's lots of directions we can take for optimizing this
                    //  sort.  For example, if the number of values being sorted meets some
                    //  criteria (such as all integers and less than 2 millions values)
                    //  then the values being sorted could be read onto the heap and sorted
                    //  in memory with a quick sort.

                    // Scan sort,
                    // The working set,
                    IIndex<RowId> workingSet = transaction.CreateTemporaryIndex<RowId>(table.RowCount);
                    // Create the resolver
                    IndexResolver resolver = CreateResolver(table, compositeExp);
                    // Iterator over the source table
                    IRowCursor tableCursor = table.GetRowCursor();

                    // Wrap in a forward prefetch iterator
                    tableCursor = new PrefetchRowCursor(tableCursor, table);

                    // Use a buffer,
                    RowId[] rowIds = new RowId[128];
                    while (tableCursor.MoveNext()) {
                        int count = 0;
                        while (tableCursor.MoveNext() && count < 128) {
                            rowIds[count] = tableCursor.Current;
                            ++count;
                        }
                        for (int i = 0; i < count; ++i) {
                            RowId rowid = rowIds[i];
                            // Get the value,
                            SqlObject[] values = resolver.GetValue(rowid);
                            // Insert the record into sorted order in the working_set
                            workingSet.Insert(values, rowid, resolver);
                        }
                    }

                    // TODO: record 'workingSet' for future resolution.

                    // The result,
                    IRowCursor sortedCursor = new DefaultRowCursor(workingSet.GetCursor());
                    SubsetTable sortedTable = new SubsetTable(table, sortedCursor);
                    sortedTable.IndexRequestFallthrough = true;
                    // Set the order composite function the describes how the subset is
                    // naturally sorted.
                    sortedTable.OrderComposite = (Expression) compositeExp.Clone();
                    resultTable = sortedTable;
                }
            }

            return resultTable;
        }
Example #3
0
        private SubsetTable FilterByIndex(ITable table, IIndexSetDataSource index, Expression order, SelectableRange range)
        {
            // Select from the index and return the subset
            IRowCursor rows = index.Select(range);
            SubsetTable filteredTable = new SubsetTable(table, rows);

            filteredTable.OrderComposite = order;

            // If the number of rows selected from the index is the same as the
            // original table, then it is safe for index requests to fallthrough to the
            // parent.
            long selectCount = rows.Count;
            long originalCount = table.RowCount;
            if (selectCount == originalCount)
                filteredTable.IndexRequestFallthrough = true;

            // Assert we didn't select more than in the original context
            if (selectCount > originalCount)
                throw new ApplicationException(	"Index found more values than in parent table.");

            return filteredTable;
        }
Example #4
0
        internal ITable FilterByScan(ITable table, Expression op)
        {
            // Default is to match table,
            ITable resultTable = table;

            long rowCount = table.RowCount;

            // If the table is not empty,
            if (rowCount > 0) {
                // Put the table on the stack,
                PushTable(table);

                // The working set,
                IIndex<RowId> workingSet = transaction.CreateTemporaryIndex<RowId>(rowCount);

                // TODO: Common expression scans should be optimized

                // Default scan (works for everything)
                // Fetch the table's row iterator
                IRowCursor cursor = table.GetRowCursor();

                // Wrap in a forward prefetch iterator
                cursor = new PrefetchRowCursor(cursor, table);

                // True if all matched
                bool allMatched = true;
                // For each value,
                while (cursor.MoveNext()) {
                    // Fetch the next row_id from the iterator
                    RowId rowid = cursor.Current;
                    // Set the top of stack table row_id
                    UpdateTableRow(rowid);

                    // Execute the expression,
                    ITable expResult = DoExecute(op);
                    // If it's true, add the row_id to the working set

                    if (BooleanResult(expResult)) {
                        // Note, we preserve the ordering of the table being filtered
                        workingSet.Add(rowid);
                    } else {
                        // Wasn't a true result, so we didn't all match.
                        allMatched = false;
                    }
                }

                // If we matched nothing
                if (workingSet.Count == 0) {
                    // Return a subset of the given table that is empty
                    SubsetTable subsetTable = new SubsetTable(table);
                    // We inherit the order composite description from the child.
                    subsetTable.SetOrderCompositeIsChild();
                    resultTable = subsetTable;
                }
                    // If we matched something
                else {
                    // If all matched we return the table
                    if (allMatched) {
                        // Clear the working set and set the result table
                        workingSet.Clear();
                        resultTable = table;
                    } else {
                        // Something in working set, and we didn't match everything,
                        IRowCursor setCursor = new DefaultRowCursor(workingSet.GetCursor());
                        SubsetTable subsetTable = new SubsetTable(table, setCursor);
                        // We inherit the order composite description from the child.
                        subsetTable.SetOrderCompositeIsChild();
                        resultTable = subsetTable;
                    }
                }

                // Pop the current table from the stack
                PopTable();
            }

            return resultTable;
        }