예제 #1
0
        /// <inheritdoc/>
        public override ITable Evaluate(IQueryContext context)
        {
            var t = Child.Evaluate(context);

            var exp = Expression;

            // Assert that all variables in the expression are identical.
            var columnNames = exp.DiscoverReferences();
            ObjectName columnName = null;
            foreach (var cv in columnNames) {
                if (columnName != null && !cv.Equals(columnName))
                    throw new InvalidOperationException("Range plan does not contain common column.");

                columnName = cv;
            }

            // Find the variable field in the table.
            var col = t.IndexOfColumn(columnName);
            if (col == -1)
                throw new InvalidOperationException("Could not find column reference in table: " + columnName);

            var field = t.TableInfo[col];

            // Calculate the range
            var range = new IndexRangeSet();
            var calculator = new RangeSetCalculator(context, field, range);
            range = calculator.Calculate(exp);

            // Select the range from the table
            var ranges = range.ToArray();
            return t.SelectRange(columnName, ranges);
        }
예제 #2
0
        /// <summary>
        /// Unions the current range set with the given range set.
        /// </summary>
        public IndexRangeSet Union(IndexRangeSet unionTo)
        {
            lock (this) {
                var rangeSet = new List<IndexRange>(ranges);
                var inputSet = unionTo.ranges;

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

                    // Insert into sorted position
                    var startPoint = inRange.StartOffset;
                    var start = inRange.StartValue;
                    var endPoint = inRange.EndOffset;
                    var end = inRange.EndValue;

                    if (start == IndexRange.FirstInSet) {
                        rangeSet.Insert(0, inRange);
                    } else {
                        var startCell = start;
                        i = rangeSet.GetRange(0, rangeSet.Count);
                        j = 0;
                        while (j < i.Count) {
                            var range = i[j];
                            var curStart = range.StartValue;
                            if (!curStart.Equals(IndexRange.FirstInSet)) {
                                if (curStart.CompareTo(startCell) > 0) {
                                    i[j] = i[j - 1];
                                    break;
                                }
                            }
                            j++;
                        }
                        i.Add(inRange);
                    }
                    n++;
                }

                return new IndexRangeSet(rangeSet);
            }
        }
예제 #3
0
 public RangeSetUpdater(IQueryContext context, ColumnInfo field, IndexRangeSet indexRangeSet)
 {
     this.context = context;
     this.field = field;
     this.indexRangeSet = indexRangeSet;
 }
예제 #4
0
            public override SqlExpression VisitBinary(SqlBinaryExpression binaryEpression)
            {
                var op = binaryEpression.ExpressionType;

                // Evaluate to an object
                var value = binaryEpression.Right.EvaluateToConstant(context, null);

                // If the evaluated object is not of a comparable type, then it becomes
                // null.
                var fieldType = field.ColumnType;
                if (!value.Type.IsComparable(fieldType))
                    value = DataObject.Null(fieldType);

                // Intersect this in the range set
                indexRangeSet = indexRangeSet.Intersect(op, value);

                return base.VisitBinary(binaryEpression);
            }
예제 #5
0
 private IndexRangeSet CalcExpression(SqlExpression expression)
 {
     var indexRangeSet = new IndexRangeSet();
     var calculator = new RangeSetCalculator(context, field, indexRangeSet);
     return calculator.Calculate(expression);
 }
예제 #6
0
            public override SqlExpression VisitBinary(SqlBinaryExpression binaryEpression)
            {
                if (binaryEpression.ExpressionType == SqlExpressionType.And) {
                    rangeSet = UpdateRange(binaryEpression.Left);
                    rangeSet = UpdateRange(binaryEpression.Right);
                } else if (binaryEpression.ExpressionType == SqlExpressionType.Or) {
                    var left = CalcExpression(binaryEpression.Left);
                    var right = CalcExpression(binaryEpression.Right);

                    rangeSet = rangeSet.Union(left);
                    rangeSet = rangeSet.Union(right);
                } else {
                    rangeSet = UpdateRange(binaryEpression);
                }

                return base.VisitBinary(binaryEpression);
            }
예제 #7
0
 public RangeSetCalculator(IQueryContext context, ColumnInfo field, IndexRangeSet rangeSet)
 {
     this.context = context;
     this.field = field;
     this.rangeSet = rangeSet;
 }
예제 #8
0
        /// <summary>
        /// Unions the current range set with the given range set.
        /// </summary>
        public IndexRangeSet Union(IndexRangeSet unionTo)
        {
            lock (this) {
                var rangeSet = new List <IndexRange>(ranges);
                var inputSet = unionTo.ranges;

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

                    // Insert into sorted position
                    var startPoint = inRange.StartOffset;
                    var start      = inRange.StartValue;
                    var endPoint   = inRange.EndOffset;
                    var end        = inRange.EndValue;

                    if (start == IndexRange.FirstInSet)
                    {
                        rangeSet.Insert(0, inRange);
                    }
                    else
                    {
                        var startCell = start;
                        i = rangeSet.GetRange(0, rangeSet.Count);
                        j = 0;
                        while (j < i.Count)
                        {
                            var range    = i[j];
                            var curStart = range.StartValue;
                            if (!curStart.Equals(IndexRange.FirstInSet))
                            {
                                if (curStart.CompareTo(startCell) > 0)
                                {
                                    i[j] = i[j - 1];
                                    break;
                                }
                            }
                            j++;
                        }
                        i.Add(inRange);
                    }
                    n++;
                }

                return(new IndexRangeSet(rangeSet));
            }
        }
예제 #9
0
        public static IEnumerable<int> SelectRows(this ITable table, int column, SqlExpressionType op, DataObject value)
        {
            // If the cell is of an incompatible type, return no results,
            var colType = table.TableInfo[column].ColumnType;
            if (!value.Type.IsComparable(colType)) {
                // Types not comparable, so return 0
                return new List<int>(0);
            }

            // Get the selectable scheme for this column
            var index = table.GetIndex(column);

            // If the operator is a standard operator, use the interned SelectableScheme
            // methods.
            if (op == SqlExpressionType.Equal)
                return index.SelectEqual(value);
            if (op == SqlExpressionType.NotEqual)
                return index.SelectNotEqual(value);
            if (op == SqlExpressionType.GreaterThan)
                return index.SelectGreater(value);
            if (op == SqlExpressionType.SmallerThan)
                return index.SelectLess(value);
            if (op == SqlExpressionType.GreaterOrEqualThan)
                return index.SelectGreaterOrEqual(value);
            if (op == SqlExpressionType.SmallerOrEqualThan)
                return index.SelectLessOrEqual(value);

            // If it's not a standard operator (such as IS, NOT IS, etc) we generate the
            // range set especially.
            var rangeSet = new IndexRangeSet();
            rangeSet = rangeSet.Intersect(op, value);
            return index.SelectRange(rangeSet.ToArray());
        }