예제 #1
0
        private int HighestSearch(DataObject ob, IList <int> list, int lower, int higher)
        {
            if ((higher - lower) <= 5)
            {
                // Start from the bottom up until we find the highest val
                for (var i = higher; i >= lower; --i)
                {
                    int res = ob.CompareTo(GetValue(list[i]));
                    if (res >= 0)
                    {
                        return(i + 1);
                    }
                }
                // Didn't find return lowest
                return(lower);
            }

            var mid        = (lower + higher) / 2;
            int compResult = ob.CompareTo(GetValue(list[mid]));

            if (compResult == 0)
            {
                // We know the bottom is between 'mid' and 'higher'
                return(HighestSearch(ob, list, mid, higher));
            }

            if (compResult < 0)
            {
                return(HighestSearch(ob, list, lower, mid - 1));
            }

            return(HighestSearch(ob, list, mid + 1, higher));
        }
예제 #2
0
        /// <summary>
        /// Searches for a given <see cref="DataObject"/> (<paramref name="ob"/>) in the
        /// row list between the two bounds.
        /// </summary>
        /// <param name="ob"></param>
        /// <param name="list"></param>
        /// <param name="lower"></param>
        /// <param name="higher"></param>
        /// <remarks>
        /// This returns the place to insert ob into the vector, it should not be used to
        /// determine if <paramref name="ob"/> is in the list or not.
        /// </remarks>
        /// <returns>
        /// This will return the highest row of the set of values that are equal to <paramref name="ob"/>.
        /// </returns>
        private long HighestSearch(DataObject ob, IList <long> list, long lower, long higher)
        {
            if ((higher - lower) <= 5)
            {
                // Start from the bottom up until we find the highest val
                for (long i = higher; i >= lower; --i)
                {
                    int res = ob.CompareTo(GetCellContents(list[(int)i]));
                    if (res >= 0)
                    {
                        return(i + 1);
                    }
                }
                // Didn't find return lowest
                return(lower);
            }

            long mid        = (lower + higher) / 2;
            int  compResult = ob.CompareTo(GetCellContents(list[(int)mid]));

            if (compResult == 0)
            {
                // We know the bottom is between 'mid' and 'higher'
                return(HighestSearch(ob, list, mid, higher));
            }

            if (compResult < 0)
            {
                return(HighestSearch(ob, list, lower, mid - 1));
            }

            return(HighestSearch(ob, list, mid + 1, higher));
        }
예제 #3
0
        /// <summary>
        /// Returns a list of rows that represent the maximum row of the given column
        /// from each distinct group in this table.
        /// </summary>
        /// <param name="colNum"></param>
        /// <remarks>
        /// This should be used to construct a virtual table of rows from
        /// each distinct group.
        /// </remarks>
        /// <returns></returns>
        private IList <long> GetMaxFromEachGroup(int colNum)
        {
            Table refTab = ReferenceTable;

            List <long> extractRows = new List <long>();
            int         size        = groupLinks.Count;

            long       toTakeInGroup = -1;
            DataObject max           = null;

            bool take = true;

            for (int i = 0; i < size; ++i)
            {
                long r = groupLinks[i];

                long       actRIndex = r & 0x03FFFFFFF;
                DataObject cell      = refTab.GetValue(colNum, actRIndex);
                if (max == null || cell.CompareTo(max) > 0)
                {
                    max           = cell;
                    toTakeInGroup = actRIndex;
                }
                if ((r & 0x040000000) != 0)
                {
                    extractRows.Add(toTakeInGroup);
                    max = null;
                }
            }

            return(extractRows);
        }
예제 #4
0
        /// <summary>
        /// Unions the current range set with the given range set.
        /// </summary>
        public void Union(SelectableRangeSet unionTo)
        {
            List <SelectableRange> inputSet = unionTo.rangeSet;

            int inSz = inputSet.Count;
            int n    = 0;

            while (n < inSz)
            {
                SelectableRange        inRange = (SelectableRange)inputSet[n];
                int                    sz      = rangeSet.Count;
                List <SelectableRange> i       = rangeSet.GetRange(0, rangeSet.Count);
                int                    j       = 0;
                while (j < i.Count)
                {
                    SelectableRange range = i[j];
                    if (RangeIntersectedBy(inRange, range))
                    {
                        i.RemoveAt(j);
                        inRange = ChangeRangeSizeToEncompass(inRange, range);
                    }
                    j++;
                }

                // Insert into sorted position
                RangePosition startPoint = inRange.StartPosition;
                DataObject    start      = inRange.Start;
                RangePosition endPoint   = inRange.EndPosition;
                DataObject    end        = inRange.End;

                if (start == SelectableRange.FirstInSet)
                {
                    rangeSet.Insert(0, inRange);
                }
                else
                {
                    DataObject startCell = start;
                    i = rangeSet.GetRange(0, rangeSet.Count);
                    j = 0;
                    while (j < i.Count)
                    {
                        SelectableRange range    = i[j];
                        DataObject      curStart = range.Start;
                        if (curStart != SelectableRange.FirstInSet)
                        {
                            if (curStart.CompareTo(startCell) > 0)
                            {
                                i[j] = i[j - 1];
                                break;
                            }
                        }
                        j++;
                    }
                    i.Add(inRange);
                }
                n++;
            }
        }
예제 #5
0
        /// <summary>
        /// Alters the first range so it encompasses the second range.
        /// </summary>
        /// <remarks>
        /// This assumes that range1 intersects range2.
        /// </remarks>
        private static SelectableRange ChangeRangeSizeToEncompass(SelectableRange range1, SelectableRange range2)
        {
            RangePosition startPosition1 = range1.StartPosition;
            DataObject    start1         = range1.Start;
            RangePosition endPosition1   = range1.EndPosition;
            DataObject    end1           = range1.End;

            RangePosition startPosition2 = range2.StartPosition;
            DataObject    start2         = range2.Start;
            RangePosition endPosition2   = range2.EndPosition;
            DataObject    end2           = range2.End;

            if (start1 != SelectableRange.FirstInSet)
            {
                if (start2 != SelectableRange.FirstInSet)
                {
                    DataObject cell = start1;
                    int        c    = cell.CompareTo(start2);
                    if (c > 0 ||
                        c == 0 && startPosition1 == RangePosition.AfterLastValue &&
                        startPosition2 == RangePosition.FirstValue)
                    {
                        start1         = start2;
                        startPosition1 = startPosition2;
                    }
                }
                else
                {
                    start1         = start2;
                    startPosition1 = startPosition2;
                }
            }

            if (end1 != SelectableRange.LastInSet)
            {
                if (end2 != SelectableRange.LastInSet)
                {
                    DataObject cell = end1;
                    int        c    = cell.CompareTo(end2);
                    if (c < 0 ||
                        c == 0 && endPosition1 == RangePosition.BeforeFirstValue &&
                        endPosition2 == RangePosition.LastValue)
                    {
                        end1         = end2;
                        endPosition1 = endPosition2;
                    }
                }
                else
                {
                    end1         = end2;
                    endPosition1 = endPosition2;
                }
            }

            return(new SelectableRange(startPosition1, start1, endPosition1, end1));
        }
예제 #6
0
        /// <summary>
        /// Returns true if the two SelectableRange ranges intersect.
        /// </summary>
        private static bool RangeIntersectedBy(SelectableRange range1, SelectableRange range2)
        {
            RangePosition startFlag1 = range1.StartPosition;
            DataObject    start1     = range1.Start;
            RangePosition endFlag1   = range1.EndPosition;
            DataObject    end1       = range1.End;

            RangePosition startFlag2 = range2.StartPosition;
            DataObject    start2     = range2.Start;
            RangePosition endFlag2   = range2.EndPosition;
            DataObject    end2       = range2.End;

            DataObject startCell1 = start1 == SelectableRange.FirstInSet ? null : start1;
            DataObject endCell1   = end1 == SelectableRange.LastInSet ? null : end1;
            DataObject startCell2 = start2 == SelectableRange.FirstInSet ? null : start2;
            DataObject endCell2   = end2 == SelectableRange.LastInSet ? null : end2;

            bool intersect1 = false;

            if (startCell1 != null && endCell2 != null)
            {
                int c = startCell1.CompareTo(endCell2);
                if (c < 0 ||
                    (c == 0 && (startFlag1 == RangePosition.FirstValue ||
                                endFlag2 == RangePosition.LastValue)))
                {
                    intersect1 = true;
                }
            }
            else
            {
                intersect1 = true;
            }

            bool intersect2 = false;

            if (startCell2 != null && endCell1 != null)
            {
                int c = startCell2.CompareTo(endCell1);
                if (c < 0 ||
                    (c == 0 && (startFlag2 == RangePosition.FirstValue ||
                                endFlag1 == RangePosition.LastValue)))
                {
                    intersect2 = true;
                }
            }
            else
            {
                intersect2 = true;
            }

            return(intersect1 && intersect2);
        }
예제 #7
0
        public static ITable Distinct(this ITable table, int[] columns)
        {
            var theTable = table as Table;

            if (theTable == null)
            {
                return(table);
            }

            List <long>  resultList = new List <long>();
            IList <long> rowList    = theTable.OrdereddRows(columns);

            long rowCount    = rowList.Count;
            long previousRow = -1;

            for (int i = 0; i < rowCount; ++i)
            {
                long rowIndex = rowList[i];

                if (previousRow != -1)
                {
                    bool equal = true;
                    // Compare cell in column in this row with previous row.
                    for (int n = 0; n < columns.Length && equal; ++n)
                    {
                        DataObject c1 = table.GetValue(columns[n], rowIndex);
                        DataObject c2 = table.GetValue(columns[n], previousRow);
                        equal = (c1.CompareTo(c2) == 0);
                    }

                    if (!equal)
                    {
                        resultList.Add(rowIndex);
                    }
                }
                else
                {
                    resultList.Add(rowIndex);
                }

                previousRow = rowIndex;
            }

            // Return the new table with distinct rows only.
            VirtualTable vt = new VirtualTable(theTable);

            vt.Set(theTable, resultList);

            return(vt);
        }
예제 #8
0
            private int InternalCompare(long index, DataObject value)
            {
                DataObject cell = scheme.GetCellContents(index);

                return(cell.CompareTo(value));
            }
예제 #9
0
        /// <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);
        }
예제 #10
0
        /// <summary>
        /// Searches for a given <see cref="DataObject"/> (<paramref name="ob"/>) in the 
        /// row list between the two bounds.
        /// </summary>
        /// <param name="ob"></param>
        /// <param name="list"></param>
        /// <param name="lower"></param>
        /// <param name="higher"></param>
        /// <remarks>
        /// This returns the place to insert ob into the vector, it should not be used to 
        /// determine if <paramref name="ob"/> is in the list or not.
        /// </remarks>
        /// <returns>
        /// This will return the highest row of the set of values that are equal to <paramref name="ob"/>.
        /// </returns>
        private long HighestSearch(DataObject ob, IList<long> list, long lower, long higher)
        {
            if ((higher - lower) <= 5) {
                // Start from the bottom up until we find the highest val
                for (long i = higher; i >= lower; --i) {
                    int res = ob.CompareTo(GetCellContents(list[(int)i]));
                    if (res >= 0)
                        return i + 1;
                }
                // Didn't find return lowest
                return lower;
            }

            long mid = (lower + higher) / 2;
            int compResult = ob.CompareTo(GetCellContents(list[(int)mid]));

            if (compResult == 0)
                // We know the bottom is between 'mid' and 'higher'
                return HighestSearch(ob, list, mid, higher);

            if (compResult < 0)
                return HighestSearch(ob, list, lower, mid - 1);

            return HighestSearch(ob, list, mid + 1, higher);
        }
예제 #11
0
        private static IndexRange IntersectOn(IndexRange range, SqlExpressionType op, DataObject value, bool nullCheck)
        {
            var start = range.StartValue;
            var startPosition = range.StartOffset;
            var end = range.EndValue;
            var endPosition = range.EndOffset;

            bool inclusive = op == SqlExpressionType.Is ||
                             op == SqlExpressionType.Equal ||
                             op == SqlExpressionType.GreaterOrEqualThan ||
                             op == SqlExpressionType.SmallerOrEqualThan;

            if (op == SqlExpressionType.Is ||
                op == SqlExpressionType.Equal ||
                op == SqlExpressionType.GreaterThan ||
                op == SqlExpressionType.GreaterOrEqualThan) {
                // With this operator, NULL values must return null.
                if (nullCheck && value.IsNull) {
                    return IndexRange.Null;
                }

                if (start.Equals(IndexRange.FirstInSet)) {
                    start = value;
                    startPosition = inclusive ? RangeFieldOffset.FirstValue : RangeFieldOffset.AfterLastValue;
                } else {
                    int c = value.CompareTo(start);
                    if ((c == 0 && startPosition == RangeFieldOffset.FirstValue) || c > 0) {
                        start = value;
                        startPosition = inclusive ? RangeFieldOffset.FirstValue : RangeFieldOffset.AfterLastValue;
                    }
                }
            }

            if (op == SqlExpressionType.Is ||
                op == SqlExpressionType.Equal ||
                op == SqlExpressionType.SmallerThan ||
                op == SqlExpressionType.SmallerOrEqualThan) {
                // With this operator, NULL values must return null.
                if (nullCheck && value.IsNull) {
                    return IndexRange.Null;
                }

                // If start is first in set, then we have to change it to after NULL
                if (nullCheck && start.Equals(IndexRange.FirstInSet)) {
                    start = DataObject.Null();
                    startPosition = RangeFieldOffset.AfterLastValue;
                }

                if (end.Equals(IndexRange.LastInSet)) {
                    end = value;
                    endPosition = inclusive ? RangeFieldOffset.LastValue : RangeFieldOffset.BeforeFirstValue;
                } else {
                    int c = value.CompareTo(end);
                    if ((c == 0 && endPosition == RangeFieldOffset.LastValue) || c < 0) {
                        end = value;
                        endPosition = inclusive ? RangeFieldOffset.LastValue : RangeFieldOffset.BeforeFirstValue;
                    }
                }
            }

            // If start and end are not null types (if either are, then it means it
            // is a placeholder value meaning start or end of set).
            if (!start.Equals(IndexRange.FirstInSet) &&
                !end.Equals(IndexRange.LastInSet)) {
                // If start is higher than end, return null
                int c = start.CompareTo(end);
                if ((c == 0 && (startPosition == RangeFieldOffset.AfterLastValue ||
                                endPosition == RangeFieldOffset.BeforeFirstValue)) ||
                    c > 0) {
                    return IndexRange.Null;
                }
            }

            // The new intersected range
            return new IndexRange(startPosition, start, endPosition, end);
        }
예제 #12
0
        private int HighestSearch(DataObject ob, IList<int> list, int lower, int higher)
        {
            if ((higher - lower) <= 5) {
                // Start from the bottom up until we find the highest val
                for (var i = higher; i >= lower; --i) {
                    int res = ob.CompareTo(GetValue(list[i]));
                    if (res >= 0)
                        return i + 1;
                }
                // Didn't find return lowest
                return lower;
            }

            var mid = (lower + higher)/2;
            int compResult = ob.CompareTo(GetValue(list[mid]));

            if (compResult == 0)
                // We know the bottom is between 'mid' and 'higher'
                return HighestSearch(ob, list, mid, higher);

            if (compResult < 0)
                return HighestSearch(ob, list, lower, mid - 1);

            return HighestSearch(ob, list, mid + 1, higher);
        }
예제 #13
0
 /// <summary>
 /// If this node represents the given entity this method should return true.
 /// </summary>
 /// <param name="entity">The entity to check.</param>
 /// <returns>true if this node represents the given entity.</returns>
 public override bool RepresentsEntity(object entity)
 {
     return (DataObject.CompareTo(entity) == 0);
 }
예제 #14
0
        /// <summary>
        /// Intersects the given SelectableRange object with the given operator and
        /// value constraint.
        /// </summary>
        /// <remarks>
        /// <b>Note</b>: This does not work with the <c>&lt;&gt;</c> operator
        /// which must be handled another way.
        /// </remarks>
        private static SelectableRange IntersectRange(SelectableRange range, Operator op, DataObject val, bool nullCheck)
        {
            DataObject    start         = range.Start;
            RangePosition startPosition = range.StartPosition;
            DataObject    end           = range.End;
            RangePosition endPosition   = range.EndPosition;

            bool inclusive = op.IsEquivalent(Operator.Is) ||
                             op.IsEquivalent(Operator.Equal) ||
                             op.IsEquivalent(Operator.GreaterOrEqual) ||
                             op.IsEquivalent(Operator.SmallerOrEqual);

            if (op.IsEquivalent(Operator.Is) ||
                op.IsEquivalent(Operator.Equal) ||
                op.IsEquivalent(Operator.Greater) ||
                op.IsEquivalent(Operator.GreaterOrEqual))
            {
                // With this operator, NULL values must return null.
                if (nullCheck && val.IsNull)
                {
                    return(null);
                }

                if (start == SelectableRange.FirstInSet)
                {
                    start         = val;
                    startPosition = inclusive
                                                                ? RangePosition.FirstValue
                                                                : RangePosition.AfterLastValue;
                }
                else
                {
                    int c = val.CompareTo(start);
                    if ((c == 0 && startPosition == RangePosition.FirstValue) || c > 0)
                    {
                        start         = val;
                        startPosition = inclusive
                                                                        ? RangePosition.FirstValue
                                                                        : RangePosition.AfterLastValue;
                    }
                }
            }
            if (op.IsEquivalent(Operator.Is) ||
                op.IsEquivalent(Operator.Equal) ||
                op.IsEquivalent(Operator.Smaller) ||
                op.IsEquivalent(Operator.SmallerOrEqual))
            {
                // With this operator, NULL values must return null.
                if (nullCheck && val.IsNull)
                {
                    return(null);
                }

                // If start is first in set, then we have to change it to after NULL
                if (nullCheck && start == SelectableRange.FirstInSet)
                {
                    start         = DataObject.Null;
                    startPosition = RangePosition.AfterLastValue;
                }

                if (end == SelectableRange.LastInSet)
                {
                    end         = val;
                    endPosition = inclusive
                                                ? RangePosition.LastValue
                                                : RangePosition.BeforeFirstValue;
                }
                else
                {
                    int c = val.CompareTo(end);
                    if ((c == 0 && endPosition == RangePosition.LastValue) || c < 0)
                    {
                        end         = val;
                        endPosition = inclusive
                                                        ? RangePosition.LastValue
                                                        : RangePosition.BeforeFirstValue;
                    }
                }
            }

            // If start and end are not null types (if either are, then it means it
            // is a placeholder value meaning start or end of set).
            if (start != SelectableRange.FirstInSet &&
                end != SelectableRange.LastInSet)
            {
                // If start is higher than end, return null
                int c = start.CompareTo(end);
                if ((c == 0 && (startPosition == RangePosition.AfterLastValue ||
                                endPosition == RangePosition.BeforeFirstValue)) ||
                    c > 0)
                {
                    return(null);
                }
            }

            // The new intersected range
            return(new SelectableRange(startPosition, start, endPosition, end));
        }
예제 #15
0
            public int CompareValue(long index, DataObject val)
            {
                DataObject cell = scheme.GetCellContents(rowSet[(int)index]);

                return(cell.CompareTo(val));
            }
예제 #16
0
            public int CompareValue(long index, DataObject val)
            {
                DataObject cell = subsetList[index];

                return(cell.CompareTo(val));
            }
예제 #17
0
        private static IndexRange IntersectOn(IndexRange range, SqlExpressionType op, DataObject value, bool nullCheck)
        {
            var start         = range.StartValue;
            var startPosition = range.StartOffset;
            var end           = range.EndValue;
            var endPosition   = range.EndOffset;

            bool inclusive = op == SqlExpressionType.Is ||
                             op == SqlExpressionType.Equal ||
                             op == SqlExpressionType.GreaterOrEqualThan ||
                             op == SqlExpressionType.SmallerOrEqualThan;

            if (op == SqlExpressionType.Is ||
                op == SqlExpressionType.Equal ||
                op == SqlExpressionType.GreaterThan ||
                op == SqlExpressionType.GreaterOrEqualThan)
            {
                // With this operator, NULL values must return null.
                if (nullCheck && value.IsNull)
                {
                    return(IndexRange.Null);
                }

                if (start.Equals(IndexRange.FirstInSet))
                {
                    start         = value;
                    startPosition = inclusive ? RangeFieldOffset.FirstValue : RangeFieldOffset.AfterLastValue;
                }
                else
                {
                    int c = value.CompareTo(start);
                    if ((c == 0 && startPosition == RangeFieldOffset.FirstValue) || c > 0)
                    {
                        start         = value;
                        startPosition = inclusive ? RangeFieldOffset.FirstValue : RangeFieldOffset.AfterLastValue;
                    }
                }
            }

            if (op == SqlExpressionType.Is ||
                op == SqlExpressionType.Equal ||
                op == SqlExpressionType.SmallerThan ||
                op == SqlExpressionType.SmallerOrEqualThan)
            {
                // With this operator, NULL values must return null.
                if (nullCheck && value.IsNull)
                {
                    return(IndexRange.Null);
                }

                // If start is first in set, then we have to change it to after NULL
                if (nullCheck && start.Equals(IndexRange.FirstInSet))
                {
                    start         = DataObject.Null();
                    startPosition = RangeFieldOffset.AfterLastValue;
                }

                if (end.Equals(IndexRange.LastInSet))
                {
                    end         = value;
                    endPosition = inclusive ? RangeFieldOffset.LastValue : RangeFieldOffset.BeforeFirstValue;
                }
                else
                {
                    int c = value.CompareTo(end);
                    if ((c == 0 && endPosition == RangeFieldOffset.LastValue) || c < 0)
                    {
                        end         = value;
                        endPosition = inclusive ? RangeFieldOffset.LastValue : RangeFieldOffset.BeforeFirstValue;
                    }
                }
            }

            // If start and end are not null types (if either are, then it means it
            // is a placeholder value meaning start or end of set).
            if (!start.Equals(IndexRange.FirstInSet) &&
                !end.Equals(IndexRange.LastInSet))
            {
                // If start is higher than end, return null
                int c = start.CompareTo(end);
                if ((c == 0 && (startPosition == RangeFieldOffset.AfterLastValue ||
                                endPosition == RangeFieldOffset.BeforeFirstValue)) ||
                    c > 0)
                {
                    return(IndexRange.Null);
                }
            }

            // The new intersected range
            return(new IndexRange(startPosition, start, endPosition, end));
        }
예제 #18
0
        /// <summary>
        /// Intersects the given SelectableRange object with the given operator and
        /// value constraint.
        /// </summary>
        /// <remarks>
        /// <b>Note</b>: This does not work with the <c>&lt;&gt;</c> operator 
        /// which must be handled another way.
        /// </remarks>
        private static SelectableRange IntersectRange(SelectableRange range, Operator op, DataObject val, bool nullCheck)
        {
            DataObject start = range.Start;
            RangePosition startPosition = range.StartPosition;
            DataObject end = range.End;
            RangePosition endPosition = range.EndPosition;

            bool inclusive = op.IsEquivalent(Operator.Is) ||
                             op.IsEquivalent(Operator.Equal) ||
                             op.IsEquivalent(Operator.GreaterOrEqual) ||
                             op.IsEquivalent(Operator.SmallerOrEqual);

            if (op.IsEquivalent(Operator.Is) ||
                op.IsEquivalent(Operator.Equal) ||
                op.IsEquivalent(Operator.Greater) ||
                op.IsEquivalent(Operator.GreaterOrEqual)) {
                // With this operator, NULL values must return null.
                if (nullCheck && val.IsNull) {
                    return null;
                }

                if (start == SelectableRange.FirstInSet) {
                    start = val;
                    startPosition = inclusive
                                        ? RangePosition.FirstValue
                                        : RangePosition.AfterLastValue;
                } else {
                    int c = val.CompareTo(start);
                    if ((c == 0 && startPosition == RangePosition.FirstValue) || c > 0) {
                        start = val;
                        startPosition = inclusive
                                            ? RangePosition.FirstValue
                                            : RangePosition.AfterLastValue;
                    }
                }
            }
            if (op.IsEquivalent(Operator.Is) ||
                op.IsEquivalent(Operator.Equal) ||
                op.IsEquivalent(Operator.Smaller) ||
                op.IsEquivalent(Operator.SmallerOrEqual)) {
                // With this operator, NULL values must return null.
                if (nullCheck && val.IsNull) {
                    return null;
                }

                // If start is first in set, then we have to change it to after NULL
                if (nullCheck && start == SelectableRange.FirstInSet) {
                    start = DataObject.Null;
                    startPosition = RangePosition.AfterLastValue;
                }

                if (end == SelectableRange.LastInSet) {
                    end = val;
                    endPosition = inclusive
                        ? RangePosition.LastValue
                        : RangePosition.BeforeFirstValue;
                } else {
                    int c = val.CompareTo(end);
                    if ((c == 0 && endPosition == RangePosition.LastValue) || c < 0) {
                        end = val;
                        endPosition = inclusive
                            ? RangePosition.LastValue
                            : RangePosition.BeforeFirstValue;
                    }
                }
            }

            // If start and end are not null types (if either are, then it means it
            // is a placeholder value meaning start or end of set).
            if (start != SelectableRange.FirstInSet &&
                end != SelectableRange.LastInSet) {
                // If start is higher than end, return null
                int c = start.CompareTo(end);
                if ((c == 0 && (startPosition == RangePosition.AfterLastValue ||
                                endPosition == RangePosition.BeforeFirstValue)) ||
                    c > 0) {
                    return null;
                }
            }

            // The new intersected range
            return new SelectableRange(startPosition, start, endPosition, end);
        }