18 using System.Collections.Generic;
26 namespace Deveel.Data.Sql.Tables {
46 private static int uniqueKeySeq = 0;
49 : this(queryContext.
Query.
Session.Transaction.
Database.SingleRowTable, functionList, columnNames, queryContext) {
56 uniqueId = uniqueKeySeq;
60 uniqueId = (uniqueId & 0x0FFFFFFF) | 0x010000000;
62 context = queryContext;
65 varResolver = table.GetVariableResolver();
66 varResolver = varResolver.ForRow(0);
69 funTableInfo =
new TableInfo(FunctionTableName);
72 expInfo =
new byte[functionList.Length];
76 for (
int i = 0; i < functionList.Length; ++i) {
77 var expr = functionList[i];
79 if (expr.IsConstant() && !expr.HasAggregate(context)) {
81 var result = expr.
Evaluate(context, null);
83 throw new InvalidOperationException();
95 funTableInfo.AddColumn(columnNames[i], expr.ReturnType(context, varResolver));
99 funTableInfo = funTableInfo.AsReadOnly();
115 get {
return funTableInfo; }
118 public override int RowCount {
119 get {
return rowCount; }
150 if (expInfo[columnOffset] == 0 && cache != null) {
152 if (cache.TryGetValue(context.Query.Session.Transaction.Database.Name, uniqueId, (
int)rowNumber, columnOffset, out cell))
157 return CalcValue((
int)rowNumber, columnOffset, cache);
161 return CalcValue((
int)rowNumber, columnOffset, null);
166 var resolver = varResolver.ForRow(row);
168 if (groupResolver != null) {
172 var expr = expList[column];
173 var exp = expr.Evaluate(context, resolver, groupResolver);
175 throw new ArgumentException();
179 cache.
Set(context.Query.Session.Transaction.Database.Name, uniqueId, row, column, value);
185 return groupLookup[rowIndex];
190 int i = groupLinks[groupNumber];
191 while ((i & 0x040000000) == 0) {
194 i = groupLinks[groupNumber];
200 var rows =
new List<int>();
201 var row = groupLinks[groupNumber];
203 while ((row & 0x040000000) == 0) {
206 row = groupLinks[groupNumber];
209 rows.Add(row & 0x03FFFFFFF);
214 var extractRows =
new List<int>();
215 var size = groupLinks.Count;
218 for (
int i = 0; i < size; ++i) {
219 int r = groupLinks[i];
221 extractRows.Add(r & 0x03FFFFFFF);
223 take = (r & 0x040000000) != 0;
232 var extractRows =
new List<int>();
233 var size = groupLinks.Count;
235 int toTakeInGroup = -1;
238 for (
int i = 0; i < size; ++i) {
239 int row = groupLinks[i];
241 int actRIndex = row & 0x03FFFFFFF;
242 var cell = refTab.GetValue(actRIndex, colNum);
244 if (max == null || cell.
CompareTo(max) > 0) {
246 toTakeInGroup = actRIndex;
249 if ((row & 0x040000000) != 0) {
250 extractRows.
Add(toTakeInGroup);
263 if (wholeTableAsGroup) {
266 rowList =
new List<int>(1);
268 if (rowEnum.MoveNext()) {
269 rowList.Add(rowEnum.Current.RowId.RowNumber);
275 rowList.Add(Int32.MaxValue - 1);
277 }
else if (table.RowCount == 0) {
278 rowList =
new List<int>(0);
279 }
else if (groupLinks != null) {
282 if (maxColumn == null) {
283 rowList = GetTopRowsFromEachGroup();
286 rowList = GetMaxFromEachGroup(colNum);
294 int rowCount = table.RowCount;
295 rowList =
new List<int>(rowCount);
296 var en = table.GetEnumerator();
297 while (en.MoveNext()) {
298 rowList.Add(en.Current.RowId.RowNumber);
305 var tabs =
new [] { table,
this };
306 var rowSets =
new[] { rowList, rowList };
313 wholeTableAsGroup =
true;
321 if (!wholeTableIsSimpleEnum) {
323 while (en.MoveNext()) {
324 wholeTableGroup.Add(en.Current.RowId.RowNumber);
335 if (RowCount <= 0 || columns.Length <= 0)
340 int[] colLookup =
new int[columns.Length];
341 for (
int i = columns.Length - 1; i >= 0; --i) {
342 colLookup[i] = rootTable.IndexOfColumn(columns[i]);
345 var rowList = rootTable.OrderRowsByColumns(colLookup).ToList();
356 groupLookup =
new List<int>(rowCount);
357 groupLinks =
new List<int>(rowCount);
358 int currentGroup = 0;
359 int previousRow = -1;
360 for (
int i = 0; i < rowCount; i++) {
361 var rowIndex = rowList[i];
363 if (previousRow != -1) {
366 for (
int n = 0; n < colLookup.Length && equal; ++n) {
367 var c1 = rootTable.GetValue(rowIndex, colLookup[n]);
368 var c2 = rootTable.GetValue(previousRow, colLookup[n]);
369 equal = (c1.CompareTo(c2) == 0);
374 groupLinks.Add(previousRow | 0x040000000);
375 currentGroup = groupLinks.Count;
377 groupLinks.Add(previousRow);
382 PlaceAt(groupLookup, rowIndex, currentGroup);
384 previousRow = rowIndex;
388 groupLinks.Add(previousRow | 0x040000000);
396 private static void PlaceAt(IList<int> list,
int index,
int value) {
397 while (index > list.Count) {
401 list.Insert(index, value);
405 var exp =
new [] { expression };
406 var names =
new[] {
"result" };
420 #region TableGroupResolver
433 public int GroupId {
get;
private set; }
438 return Table.wholeTableGroupSize;
442 return Table.GetGroupSize(GroupId);
449 group =
Table.wholeTableGroup;
451 group =
Table.GetGroupRows(GroupId);
459 throw new InvalidOperationException(
String.Format(
"Column {0} not found in table {1}.", variable,
Table.TableName));
463 int rowIndex = setIndex;
465 rowIndex = group[setIndex];
471 if (groupVarResolver == null)
474 return groupVarResolver;
478 var resolver = CreateVariableResolver();
479 resolver = resolver.ForRow(setIndex);
484 if (
Table.wholeTableAsGroup) {
490 int g =
Table.GetRowGroup(rowIndex);
498 #region GroupVariableResolver
505 : this(groupResolver, -1) {
509 this.groupResolver = groupResolver;
510 this.rowIndex = rowIndex;
515 throw new InvalidOperationException();
517 return groupResolver.Resolve(variable, rowIndex);
521 var columnOffset = groupResolver.Table.FindColumn(variable);
522 if (columnOffset < 0)
523 throw new InvalidOperationException(
String.Format(
"Cannot find column {0} in table {1}", variable,
524 groupResolver.Table.TableName));
526 return groupResolver.Table.TableInfo[columnOffset].ColumnType;
abstract DataObject GetValue(long rowNumber, int columnOffset)
Gets a single cell within the table that is located at the given column offset and row...
override IEnumerator< Row > GetEnumerator()
readonly TableInfo funTableInfo
static DataObject Integer(int value)
Defines the contract to access the data contained into a table of a database.
static ITable ResultTable(IRequest context, DataObject value)
ITable MergeWith(ObjectName maxColumn)
void Set(CachedCell cell)
FunctionTable(SqlExpression[] functionList, string[] columnNames, IRequest queryContext)
A long string in the system.
FunctionTable CreateGroupMatrix(ObjectName[] columns)
SqlType ReturnType(ObjectName variable)
Returns the SqlType of object the given variable is.
static void PlaceAt(IList< int > list, int index, int value)
ITableCellCache TableCellCache()
static ITable ResultTable(IRequest context, SqlExpression expression)
IList< int > wholeTableGroup
int GetGroupSize(int groupNumber)
ITableVariableResolver ForRow(int rowNum)
int FindColumn(ObjectName columnName)
IVariableResolver GetVariableResolver(int setIndex)
Returns a IVariableResolver that can be used to resolve variable in the get set of the group...
TableGroupResolver(FunctionTable table)
The default implementation of a database in a system.
Describes the name of an object within a database.
DataObject Resolve(ObjectName variable)
Returns the value of a given variable.
DataObject CalcValue(int row, int column, ITableCellCache cache)
ITableVariableResolver CreateVariableResolver()
DataObject Resolve(ObjectName variable, int setIndex)
Returns the value of a variable of a group.
override DataObject GetValue(long rowNumber, int columnOffset)
Gets a single cell within the table that is located at the given column offset and row...
IList< int > GetMaxFromEachGroup(int colNum)
SqlExpressionType
All the possible type of SqlExpression supported
This is a session that is constructed around a given user and a transaction, to the given database...
GroupVariableResolver(TableGroupResolver groupResolver, int rowIndex)
virtual SqlExpression Evaluate(EvaluateContext context)
When overridden by a derived class, this method evaluates the expression within the provided context...
bool wholeTableIsSimpleEnum
IList< int > GetTopRowsFromEachGroup()
int GetRowGroup(int rowIndex)
int CompareTo(DataObject other)
Defines a contract used by grouping functions to find information about the current group being evalu...
Represents a dynamic object that encapsulates a defined SqlType and a compatible constant ISqlObject ...
IList< int > GetGroupRows(int groupNumber)
GroupVariableResolver(TableGroupResolver groupResolver)
readonly ITableVariableResolver varResolver
Defines the properties of a specific SQL Type and handles the values compatible.
int RowCount
Gets the total number of rows in the table.
An interface to resolve a variable name to a constant object.
An expression that holds a constant value.
readonly TableGroupResolver groupResolver
Defines the base class for instances that represent SQL expression tree nodes.
static SqlConstantExpression Constant(object value)
static ITable ResultTable(IRequest context, int value)
Defines the metadata properties of a table existing within a database.
DataObject Add(DataObject other)
Adds the given value to this object value.
override IEnumerator< Row > GetEnumerator()
readonly IRequest context
void SetUpGroupForRow(int rowIndex)
readonly SqlExpression[] expList
ITableVariableResolver groupVarResolver
TableGroupResolver groupResolver
FunctionTable(ITable table, SqlExpression[] functionList, string[] columnNames, IRequest queryContext)