private IndexRangeSet CalcExpression(SqlExpression expression)
            {
                var indexRangeSet = new IndexRangeSet();
                var calculator    = new RangeSetCalculator(context, field, indexRangeSet);

                return(calculator.Calculate(expression));
            }
        /// <inheritdoc/>
        public override ITable Evaluate(IRequest 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));
        }
            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 = Field.Null(fieldType);
                }

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

                return(base.VisitBinary(binaryEpression));
            }
            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));
            }
 public RangeSetCalculator(IRequest context, ColumnInfo field, IndexRangeSet rangeSet)
 {
     this.context  = context;
     this.field    = field;
     this.rangeSet = rangeSet;
 }
 public RangeSetUpdater(IRequest context, ColumnInfo field, IndexRangeSet indexRangeSet)
 {
     this.context       = context;
     this.field         = field;
     this.indexRangeSet = indexRangeSet;
 }