DeveelDB  20151217
complete SQL database system, primarly developed for .NET/Mono frameworks
RangeSelectNode.cs
Go to the documentation of this file.
1 //
2 // Copyright 2010-2015 Deveel
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 using System;
18 
19 using Deveel.Data;
20 using Deveel.Data.Index;
23 using Deveel.Data.Sql.Tables;
24 
25 namespace Deveel.Data.Sql.Query {
52  [Serializable]
54  public RangeSelectNode(IQueryPlanNode child, SqlExpression expression)
55  : base(child) {
56  Expression = expression;
57  }
58 
60  : base(data) {
61  Expression = data.GetValue<SqlExpression>("Expression");
62  }
63 
69  public SqlExpression Expression { get; private set; }
70 
71  protected override void GetData(SerializeData data) {
72  data.SetValue("Expression", Expression);
73  }
74 
76  public override ITable Evaluate(IRequest context) {
77  var t = Child.Evaluate(context);
78 
79  var exp = Expression;
80 
81  // Assert that all variables in the expression are identical.
82  var columnNames = exp.DiscoverReferences();
83  ObjectName columnName = null;
84  foreach (var cv in columnNames) {
85  if (columnName != null && !cv.Equals(columnName))
86  throw new InvalidOperationException("Range plan does not contain common column.");
87 
88  columnName = cv;
89  }
90 
91  // Find the variable field in the table.
92  var col = t.IndexOfColumn(columnName);
93  if (col == -1)
94  throw new InvalidOperationException("Could not find column reference in table: " + columnName);
95 
96  var field = t.TableInfo[col];
97 
98  // Calculate the range
99  var range = new IndexRangeSet();
100  var calculator = new RangeSetCalculator(context, field, range);
101  range = calculator.Calculate(exp);
102 
103  // Select the range from the table
104  var ranges = range.ToArray();
105  return t.SelectRange(columnName, ranges);
106  }
107 
108  #region RangeSetUpdater
109 
112  private readonly IRequest context;
113  private readonly ColumnInfo field;
114 
115  public RangeSetUpdater(IRequest context, ColumnInfo field, IndexRangeSet indexRangeSet) {
116  this.context = context;
117  this.field = field;
118  this.indexRangeSet = indexRangeSet;
119  }
120 
121  public IndexRangeSet Update(SqlExpression expression) {
122  Visit(expression);
123  return indexRangeSet;
124  }
125 
126  public override SqlExpression VisitBinary(SqlBinaryExpression binaryEpression) {
127  var op = binaryEpression.ExpressionType;
128 
129  // Evaluate to an object
130  var value = binaryEpression.Right.EvaluateToConstant(context, null);
131 
132  // If the evaluated object is not of a comparable type, then it becomes
133  // null.
134  var fieldType = field.ColumnType;
135  if (!value.Type.IsComparable(fieldType))
136  value = DataObject.Null(fieldType);
137 
138  // Intersect this in the range set
139  indexRangeSet = indexRangeSet.Intersect(op, value);
140 
141  return base.VisitBinary(binaryEpression);
142  }
143  }
144 
145  #endregion
146 
147  #region RangeSetCalculator
148 
151  private readonly IRequest context;
152  private readonly ColumnInfo field;
153 
154  public RangeSetCalculator(IRequest context, ColumnInfo field, IndexRangeSet rangeSet) {
155  this.context = context;
156  this.field = field;
157  this.rangeSet = rangeSet;
158  }
159 
161  var updater = new RangeSetUpdater(context, field, rangeSet);
162  return updater.Update(expression);
163  }
164 
166  var indexRangeSet = new IndexRangeSet();
167  var calculator = new RangeSetCalculator(context, field, indexRangeSet);
168  return calculator.Calculate(expression);
169  }
170 
171  public override SqlExpression VisitBinary(SqlBinaryExpression binaryEpression) {
172  if (binaryEpression.ExpressionType == SqlExpressionType.And) {
173  rangeSet = UpdateRange(binaryEpression.Left);
174  rangeSet = UpdateRange(binaryEpression.Right);
175  } else if (binaryEpression.ExpressionType == SqlExpressionType.Or) {
176  var left = CalcExpression(binaryEpression.Left);
177  var right = CalcExpression(binaryEpression.Right);
178 
179  rangeSet = rangeSet.Union(left);
180  rangeSet = rangeSet.Union(right);
181  } else {
182  rangeSet = UpdateRange(binaryEpression);
183  }
184 
185  return base.VisitBinary(binaryEpression);
186  }
187 
188  public IndexRangeSet Calculate(SqlExpression expression) {
189  Visit(expression);
190  return rangeSet;
191  }
192  }
193 
194  #endregion
195  }
196 }
Defines the metadata properties of a column within a table of a database.
Definition: ColumnInfo.cs:36
override void GetData(SerializeData data)
Defines the contract to access the data contained into a table of a database.
Definition: ITable.cs:40
override SqlExpression VisitBinary(SqlBinaryExpression binaryEpression)
A IQueryPlanNode with a single child.
static DataObject Null(SqlType type)
Definition: DataObject.cs:630
void SetValue(string key, Type type, object value)
Describes the name of an object within a database.
Definition: ObjectName.cs:44
SqlExpressionType
All the possible type of SqlExpression supported
The node for performing a simple indexed query on a single column of the child node.
override SqlExpression VisitBinary(SqlBinaryExpression binaryEpression)
A node element of a query plan tree. /summary>
RangeSelectNode(IQueryPlanNode child, SqlExpression expression)
IndexRangeSet CalcExpression(SqlExpression expression)
IndexRangeSet Update(SqlExpression expression)
Represents a dynamic object that encapsulates a defined SqlType and a compatible constant ISqlObject ...
Definition: DataObject.cs:35
IndexRangeSet Intersect(SqlExpressionType op, DataObject value)
override ITable Evaluate(IRequest context)
Defines the base class for instances that represent SQL expression tree nodes.
IndexRangeSet Calculate(SqlExpression expression)
IndexRangeSet UpdateRange(SqlExpression expression)
RangeSetCalculator(IRequest context, ColumnInfo field, IndexRangeSet rangeSet)
IndexRangeSet Union(IndexRangeSet unionTo)
Unions the current range set with the given range set.
RangeSetUpdater(IRequest context, ColumnInfo field, IndexRangeSet indexRangeSet)