Describes the range of values to select from an index.
A range has a start value, an end value, and whether we should pick inclusive or exclusive of the end value. The start value may be a concrete value from the set or it may be a flag that represents the start or end of the list.

Note that the the start value may not compare less than the end value. For example, start can not be RangeFieldOffset.LastValue and end can not be RangeFieldOffset.FirstValue.

        public override IEnumerable<int> SelectRange(IndexRange[] ranges)
        {
            int setSize = Table.RowCount;
            // If no items in the set return an empty set
            if (setSize == 0)
                return new List<int>(0);

            var checker = new RangeChecker(this, ranges);
            return checker.Resolve();
        }
        public override IEnumerable<int> SelectRange(IndexRange[] ranges)
        {
            // If no items in the set return an empty set
            if (Count == 0)
                return new List<int>(0);

            IEnumerable<int> list = null;
            foreach (var range in ranges) {
                list = AddRange(range, list);
            }

            if (list == null)
                return new List<int>(0);

            return list;
        }
Beispiel #3
0
        private static IndexRange IntersectOn(IndexRange range, SqlExpressionType op, Field 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 = Field.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);
        }
Beispiel #4
0
        /// <summary>
        /// Returns true if the two SelectableRange ranges intersect.
        /// </summary>
        private static bool IntersectedBy(IndexRange range1, IndexRange range2)
        {
            var startFlag1 = range1.StartOffset;
            var start1 = range1.StartValue;
            var endFlag1 = range1.EndOffset;
            var end1 = range1.EndValue;

            var startFlag2 = range2.StartOffset;
            var start2 = range2.StartValue;
            var endFlag2 = range2.EndOffset;
            var end2 = range2.EndValue;

            var startCell1 = start1.Equals(IndexRange.FirstInSet) ? null : start1;
            var endCell1 = end1.Equals(IndexRange.LastInSet) ? null : end1;
            var startCell2 = start2.Equals(IndexRange.FirstInSet) ? null : start2;
            var endCell2 = end2.Equals(IndexRange.LastInSet) ? null : end2;

            bool intersect1 = false;
            if (startCell1 != null && endCell2 != null) {
                int c = startCell1.CompareTo(endCell2);
                if (c < 0 ||
                    (c == 0 && (startFlag1 == RangeFieldOffset.FirstValue ||
                                endFlag2 == RangeFieldOffset.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 == RangeFieldOffset.FirstValue ||
                                endFlag1 == RangeFieldOffset.LastValue))) {
                    intersect2 = true;
                }
            } else {
                intersect2 = true;
            }

            return (intersect1 && intersect2);
        }
Beispiel #5
0
        /// <summary>
        /// Alters the first range so it encompasses the second range.
        /// </summary>
        /// <remarks>
        /// This assumes that range1 intersects range2.
        /// </remarks>
        private static IndexRange ChangeRangeSizeToEncompass(IndexRange range1, IndexRange range2)
        {
            var startPosition1 = range1.StartOffset;
            var start1 = range1.StartValue;
            var endPosition1 = range1.EndOffset;
            var end1 = range1.EndValue;

            var startPosition2 = range2.StartOffset;
            var start2 = range2.StartValue;
            var endPosition2 = range2.EndOffset;
            var end2 = range2.EndValue;

            if (!start1.Equals(IndexRange.FirstInSet)) {
                if (!start2.Equals(IndexRange.FirstInSet)) {
                    var cell = start1;
                    int c = cell.CompareTo(start2);
                    if (c > 0 ||
                        c == 0 && startPosition1 == RangeFieldOffset.AfterLastValue &&
                        startPosition2 == RangeFieldOffset.FirstValue) {
                        start1 = start2;
                        startPosition1 = startPosition2;
                    }
                } else {
                    start1 = start2;
                    startPosition1 = startPosition2;
                }
            }

            if (!end1.Equals(IndexRange.LastInSet)) {
                if (!end2.Equals(IndexRange.LastInSet)) {
                    var cell = end1;
                    int c = cell.CompareTo(end2);
                    if (c < 0 ||
                        c == 0 && endPosition1 == RangeFieldOffset.BeforeFirstValue &&
                        endPosition2 == RangeFieldOffset.LastValue) {
                        end1 = end2;
                        endPosition1 = endPosition2;
                    }
                } else {
                    end1 = end2;
                    endPosition1 = endPosition2;
                }
            }

            return new IndexRange(startPosition1, start1, endPosition1, end1);
        }
        private IEnumerable<int> AddRange(IndexRange range, IEnumerable<int> list)
        {
            // Select the range specified.
            var startFlag = range.StartOffset;
            var start = range.StartValue;
            var endFlag = range.EndOffset;
            var end = range.EndValue;

            int r1 = PositionOfRangePoint(startFlag, start);
            int r2 = PositionOfRangePoint(endFlag, end);

            if (r2 < r1)
                return list;

            // Add the range to the set
            return AddRange(r1, r2, list);
        }
            /// <summary>
            /// Set up a range.
            /// </summary>
            /// <param name="i"></param>
            /// <param name="range"></param>
            private void SetupRange(int i, IndexRange range)
            {
                var l = range.StartValue;
                var lf = range.StartOffset;
                var u = range.EndValue;
                var uf = range.EndOffset;

                // Handle lower first
                if (l.Equals(IndexRange.FirstInSet) &&
                    lf.Equals(RangeFieldOffset.FirstValue)) {
                    // Special case no lower check
                    lowerFlags[i] = NoCheck;
                } else {
                    if (lf.Equals(RangeFieldOffset.FirstValue)) {
                        lowerFlags[i] = CheckLesserEqualOrGreaterEqual;  // >=
                    } else if (lf.Equals(RangeFieldOffset.AfterLastValue)) {
                        lowerFlags[i] = CheckLesserOrGreater;  // >
                    } else {
                        throw new InvalidOperationException("Incorrect lower flag.");
                    }
                    lowerCells[i] = ResolveCell(l);
                }

                // Now handle upper
                if (u.Equals(IndexRange.LastInSet) &&
                    uf.Equals(RangeFieldOffset.LastValue)) {
                    // Special case no upper check
                    upperFlags[i] = NoCheck;
                } else {
                    if (uf.Equals(RangeFieldOffset.LastValue)) {
                        upperFlags[i] = CheckLesserEqualOrGreaterEqual;  // <=
                    } else if (uf.Equals( RangeFieldOffset.BeforeFirstValue)) {
                        upperFlags[i] = CheckLesserOrGreater;  // <
                    } else {
                        throw new InvalidOperationException("Incorrect upper flag.");
                    }
                    upperCells[i] = ResolveCell(u);
                }
            }
            public RangeChecker(BlindSearchIndex scheme, IndexRange[] ranges)
            {
                this.scheme = scheme;

                int size = ranges.Length;
                lowerFlags = new byte[size];
                upperFlags = new byte[size];
                lowerCells = new DataObject[size];
                upperCells = new DataObject[size];
                for (int i = 0; i < ranges.Length; ++i) {
                    SetupRange(i, ranges[i]);
                }
            }
        public static ITable SelectRange(this ITable thisTable, ObjectName columnName, IndexRange[] ranges)
        {
            // If this table is empty then there is no range to select so
            // trivially return this object.
            if (thisTable.RowCount == 0)
                return thisTable;

            // Are we selecting a black or null range?
            if (ranges == null || ranges.Length == 0)
                // Yes, so return an empty table
                return thisTable.EmptySelect();

            // Are we selecting the entire range?
            if (ranges.Length == 1 &&
                ranges[0].Equals(IndexRange.FullRange))
                // Yes, so return this table.
                return thisTable;

            // Must be a non-trivial range selection.

            // Find the column index of the column selected
            int column = thisTable.IndexOfColumn(columnName);

            if (column == -1) {
                throw new Exception(
                    "Unable to find the column given to select the range of: " +
                    columnName.Name);
            }

            // Select the range
            var rows = thisTable.SelectRowsRange(column, ranges);

            // Make a new table with the range selected
            var result = new VirtualTable(thisTable, rows.ToArray());

            // We know the new set is ordered by the column.
            result.SortColumn = column;

            return result;
        }
 public static IEnumerable<int> SelectRowsRange(this ITable table, int column, IndexRange[] ranges)
 {
     return table.GetIndex(column).SelectRange(ranges);
 }
Beispiel #11
0
 public override IEnumerable<int> SelectRange(IndexRange[] ranges)
 {
     throw new NotImplementedException();
 }