public static IEnumerable <long> SelectRows(this ITable table, int column, Operator op, DataObject cell) { // If the cell is of an incompatible type, return no results, DataType colType = table.TableInfo[column].DataType; if (!cell.DataType.IsComparable(colType)) { // Types not comparable, so return 0 return(new List <long>(0)); } // Get the selectable scheme for this column SelectableScheme ss = table.GetScheme(column); // If the operator is a standard operator, use the interned SelectableScheme // methods. if (op.IsEquivalent(Operator.Equal)) { return(ss.SelectEqual(cell)); } if (op.IsEquivalent(Operator.NotEqual)) { return(ss.SelectNotEqual(cell)); } if (op.IsEquivalent(Operator.Greater)) { return(ss.SelectGreater(cell)); } if (op.IsEquivalent(Operator.Smaller)) { return(ss.SelectLess(cell)); } if (op.IsEquivalent(Operator.GreaterOrEqual)) { return(ss.SelectGreaterOrEqual(cell)); } if (op.IsEquivalent(Operator.SmallerOrEqual)) { return(ss.SelectLessOrEqual(cell)); } // If it's not a standard operator (such as IS, NOT IS, etc) we generate the // range set especially. SelectableRangeSet rangeSet = new SelectableRangeSet(); rangeSet.Intersect(op, cell); return(ss.SelectRange(rangeSet.ToArray())); }
/// <summary> /// Calculates a list of <see cref="SelectableRange"/> objects that represent /// the range of the expression. /// </summary> /// <param name="context"></param> /// <param name="field"></param> /// <param name="range"></param> /// <param name="exp"></param> private static void CalcRange(IQueryContext context, DataColumnInfo field, SelectableRangeSet range, Expression exp) { var binary = (BinaryExpression)exp; Operator op = binary.Operator; if (op.IsLogical()) { if (op == Operator.And) { IList <Expression> andList = CreateAndList(new List <Expression>(), exp); foreach (Expression expr in andList) { UpdateRange(context, range, field, expr); } } else if (op == Operator.Or) { // Split left and right of logical operator. Expression[] exps = { binary.Left, binary.Right }; // Calculate the range of the left and right SelectableRangeSet left = new SelectableRangeSet(); CalcRange(context, field, left, exps[0]); SelectableRangeSet right = new SelectableRangeSet(); CalcRange(context, field, right, exps[1]); // Union the left and right range with the current range range.Union(left); range.Union(right); } else { throw new ApplicationException("Unrecognised logical operator."); } } else { // Not an operator so this is the value. UpdateRange(context, range, field, exp); } }
/// <summary> /// Updates a range with the given expression. /// </summary> /// <param name="context"></param> /// <param name="range"></param> /// <param name="field"></param> /// <param name="e"></param> private static void UpdateRange(IQueryContext context, SelectableRangeSet range, DataColumnInfo field, Expression e) { var binary = (BinaryExpression)e; Operator op = binary.Operator; Expression[] exps = { binary.Left, binary.Right }; // Evaluate to an object DataObject cell = exps[1].Evaluate(context); // If the evaluated object is not of a comparable type, then it becomes // null. DataType fieldType = field.DataType; if (!cell.DataType.IsComparable(fieldType)) { cell = new DataObject(fieldType, null); } // Intersect this in the range set range.Intersect(op, cell); }
public override ITable Evaluate(IQueryContext context) { ITable t = Child.Evaluate(context); Expression exp = expression; // Assert that all variables in the expression are identical. IEnumerable <ObjectName> allVars = exp.AllVariables(); ObjectName v = null; foreach (ObjectName cv in allVars) { if (v != null && !cv.Equals(v)) { throw new ApplicationException("Assertion failed: Range plan does not contain common variable."); } v = cv; } // Find the variable field in the table. int col = ((Table)t).FindFieldName(v); if (col == -1) { throw new ApplicationException("Couldn't find column reference in table: " + v); } DataColumnInfo field = t.TableInfo[col]; // Calculate the range SelectableRangeSet range = new SelectableRangeSet(); CalcRange(context, field, range, exp); // Select the range from the table SelectableRange[] ranges = range.ToArray(); return(t.RangeSelect(v, ranges)); }