/// <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); }
/// <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); } }
public RangeSetUpdater(IQueryContext context, ColumnInfo field, IndexRangeSet indexRangeSet) { this.context = context; this.field = field; this.indexRangeSet = indexRangeSet; }
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); }
private IndexRangeSet CalcExpression(SqlExpression expression) { var indexRangeSet = new IndexRangeSet(); var calculator = new RangeSetCalculator(context, field, indexRangeSet); return calculator.Calculate(expression); }
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(IQueryContext context, ColumnInfo field, IndexRangeSet rangeSet) { this.context = context; this.field = field; this.rangeSet = rangeSet; }
/// <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)); } }
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()); }