DeveelDB  20151217
complete SQL database system, primarly developed for .NET/Mono frameworks
QuerySelectColumns.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 using System.Collections.Generic;
19 using System.Diagnostics;
20 using System.Globalization;
21 
22 using Deveel.Data;
24 
25 namespace Deveel.Data.Sql.Query {
26  sealed class QuerySelectColumns {
30  private static readonly ObjectName FunctionTableName = new ObjectName("FUNCTIONTABLE");
31 
35  private readonly QueryExpressionFrom fromSet;
36 
37  private readonly List<SelectColumn> selectedColumns;
38 
39  // The count of aggregate and constant columns included in the result set.
40  // Aggregate columns are, (count(*), avg(cost_of) * 0.75, etc). Constant
41  // columns are, (9 * 4, 2, (9 * 7 / 4) + 4, etc).
42 
44  this.fromSet = fromSet;
45  selectedColumns = new List<SelectColumn>();
46  }
47 
48  public void SelectSingleColumn(SelectColumn col) {
49  selectedColumns.Add(col);
50  }
51 
52  private void AddAllFromTable(IFromTableSource table) {
53  // Select all the tables
54  var columns = table.ColumnNames;
55  foreach (ObjectName name in columns) {
56  // Make up the SelectColumn
58  var column = new SelectColumn(e) {
59  ResolvedName = name,
60  InternalName = name
61  };
62 
63  // Add to the list of columns selected
64  SelectSingleColumn(column);
65  }
66  }
67 
68  public void SelectAllColumnsFromSource(ObjectName tableName) {
69  // Attempt to find the table in the from set.
70  string schema = null;
71  if (tableName.Parent != null)
72  schema = tableName.Parent.Name;
73 
74  IFromTableSource table = fromSet.FindTable(schema, tableName.Name);
75  if (table == null)
76  throw new InvalidOperationException(tableName + ".* is not a valid reference.");
77 
78  AddAllFromTable(table);
79  }
80 
82  for (int p = 0; p < fromSet.SourceCount; ++p) {
83  IFromTableSource table = fromSet.GetTableSource(p);
84  AddAllFromTable(table);
85  }
86  }
87 
88  private SelectColumn PrepareColumn(SelectColumn column, IRequest context, IList<SelectColumn> functionColumns,
89  ref int aggregateCount) {
90  if (column.Expression is SqlQueryExpression)
91  throw new InvalidOperationException("Sub-query expressions are invalid in select columns.");
92 
93  SelectColumn newColumn;
94 
95  var exp = column.Expression;
96  if (exp != null)
97  exp = exp.Prepare(fromSet.ExpressionPreparer);
98 
99  if (exp is SqlReferenceExpression) {
100  var sqlRef = (SqlReferenceExpression) exp;
101  var colName = sqlRef.ReferenceName;
102  ObjectName resolvedName = null;
103 
104  var alias = column.Alias;
105  if (String.IsNullOrEmpty(alias)) {
106  resolvedName = colName;
107  } else {
108  resolvedName = new ObjectName(alias);
109  }
110 
111  newColumn = new SelectColumn(exp, alias) {
112  InternalName = colName,
113  ResolvedName = resolvedName
114  };
115  } else {
116  var funcAlias = functionColumns.Count.ToString(CultureInfo.InvariantCulture);
117  if (column.Expression.HasAggregate(context)) {
118  aggregateCount++;
119  funcAlias += "_A";
120  }
121 
122  var alias = column.Alias;
123  if (string.IsNullOrEmpty(alias))
124  alias = exp.ToString();
125 
126  newColumn = new SelectColumn(exp, alias) {
127  InternalName = new ObjectName(FunctionTableName, funcAlias),
128  ResolvedName = new ObjectName(alias)
129  };
130 
131  functionColumns.Add(newColumn);
132  }
133 
134  return newColumn;
135  }
136 
138  int aggregateCount = 0;
139  var functionColumns = new List<SelectColumn>();
140  var preparedColumns = new List<SelectColumn>();
141  foreach (var column in selectedColumns) {
142  var prepared = PrepareColumn(column, context, functionColumns, ref aggregateCount);
143  preparedColumns.Add(prepared);
144  }
145 
146  return new PreparedQuerySelectColumns(preparedColumns, functionColumns, aggregateCount);
147  }
148  }
149 }
QuerySelectColumns(QueryExpressionFrom fromSet)
ObjectName[] ColumnNames
Returns an array of ObjectName objects that references each column available in the table set item in...
override string ToString()
Definition: ObjectName.cs:225
An expression that references an object within a context.
A single table resource item in a query which handles the behaviour of resolving references to column...
PreparedQuerySelectColumns Prepare(IRequest context)
Describes the name of an object within a database.
Definition: ObjectName.cs:44
readonly QueryExpressionFrom fromSet
The tables we are selecting from.
void AddAllFromTable(IFromTableSource table)
virtual SqlExpression Prepare(IExpressionPreparer preparer)
Represents a column selected to be in the output of a select statement.
Definition: SelectColumn.cs:31
SqlExpression Expression
Gets the expression used to select the column.
Definition: SelectColumn.cs:65
SelectColumn PrepareColumn(SelectColumn column, IRequest context, IList< SelectColumn > functionColumns, ref int aggregateCount)
ObjectName Parent
Gets the parent reference of the current one, if any or null if none.
Definition: ObjectName.cs:99
string Alias
Gets the name used to alias the select expression.
Definition: SelectColumn.cs:70
void SelectAllColumnsFromSource(ObjectName tableName)
string Name
Gets the name of the object being referenced.
Definition: ObjectName.cs:108
static SqlReferenceExpression Reference(ObjectName objectName)
readonly List< SelectColumn > selectedColumns
Defines the base class for instances that represent SQL expression tree nodes.