DeveelDB  20151217
complete SQL database system, primarly developed for .NET/Mono frameworks
FromClause.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.Globalization;
20 using System.IO;
21 
23 
24 namespace Deveel.Data.Sql.Expressions {
31  [Serializable]
32  public sealed class FromClause : IPreparable, ISerializable {
33  public FromClause() {
34  fromTables = new List<FromTable>();
35  joinParts = new List<JoinPart>();
36  tableNames = new List<string>();
37  }
38 
39  private FromClause(ObjectData data) {
40  var tableNames = data.GetValue<string[]>("TableNames");
41  var fromTables = data.GetValue<FromTable[]>("FromTables");
42  var joinParts = data.GetValue<JoinPart[]>("JoinParts");
43 
44  this.tableNames = new List<string>();
45  this.fromTables = new List<FromTable>();
46  this.joinParts = new List<JoinPart>();
47 
48  if (tableNames != null)
49  this.tableNames.AddRange(tableNames);
50  if (fromTables != null)
51  this.fromTables.AddRange(fromTables);
52  if (joinParts != null)
53  this.joinParts.AddRange(joinParts);
54  }
55 
56  private readonly List<string> tableNames;
57  private readonly List<FromTable> fromTables;
58  private readonly List<JoinPart> joinParts;
59 
63  private int tableKey;
64 
68  public IEnumerable<FromTable> AllTables {
69  get { return fromTables.ToArray(); }
70  }
71 
75  public int JoinPartCount {
76  get { return joinParts.Count; }
77  }
78 
79  public bool IsEmpty {
80  get { return fromTables.Count == 0; }
81  }
82 
83  private String CreateNewKey() {
84  ++tableKey;
85  return tableKey.ToString(CultureInfo.InvariantCulture);
86  }
87 
93  public void AddTable(string alias, FromTable table) {
94  if (table == null)
95  throw new ArgumentNullException("table");
96 
97  if (!String.IsNullOrEmpty(alias)) {
98  if (tableNames.Contains(alias))
99  throw new ArgumentException(String.Format("Duplicated table name {0} is FROM clause.", alias));
100 
101  tableNames.Add(alias);
102  }
103 
104  // Create a new unique key for this table
105  string key = CreateNewKey();
106  table.UniqueKey = key;
107  fromTables.Add(table);
108  }
109 
116  public void AddTable(string alias, string tableName) {
117  AddTable(alias, new FromTable(tableName, alias));
118  }
119 
125  public void AddTable(string tableName) {
126  AddTable(null, tableName);
127  }
128 
134  public void AddSubQuery(SqlQueryExpression subQuery) {
135  AddSubQuery(null, subQuery);
136  }
137 
145  public void AddSubQuery(string alias, SqlQueryExpression subQuery) {
146  AddTable(alias, new FromTable(subQuery, alias));
147  }
148 
154  public void Join(JoinType joinType, SqlExpression onExpression) {
155  var lastTable = fromTables[fromTables.Count - 1];
156  if (lastTable.IsSubQuery) {
157  var subQuery = lastTable.SubQuery;
158  joinParts.Add(new JoinPart(joinType, subQuery, onExpression));
159  } else {
160  var tableName = ObjectName.Parse(lastTable.Name);
161  joinParts.Add(new JoinPart(joinType, tableName, onExpression));
162  }
163  }
164 
174  public JoinPart GetJoinPart(int offset) {
175  return joinParts[offset];
176  }
177 
179  var clause = new FromClause();
180 
181  // Prepare expressions in the JoiningSet first
182  int size = joinParts.Count;
183  for (int i = 0; i < size; ++i) {
184  var part = joinParts[i];
185  var exp = part.OnExpression;
186  if (exp != null) {
187  exp = exp.Prepare(preparer);
188  if (part.SubQuery != null) {
189  part = new JoinPart(part.JoinType, part.SubQuery, exp);
190  } else {
191  part = new JoinPart(part.JoinType, part.TableName, exp);
192  }
193  }
194 
195  clause.joinParts.Add(part);
196  }
197 
198  // Prepare the StatementTree sub-queries in the from tables
199  for (int i = 0; i < fromTables.Count; i++) {
200  var table = fromTables[i];
201  var preparedTable = (FromTable) ((IPreparable) table).Prepare(preparer);
202  var tableAlias = tableNames[i];
203  clause.tableNames.Insert(i, tableAlias);
204  clause.fromTables.Insert(i, preparedTable);
205  }
206 
207  return clause;
208  }
209 
211  if (tableNames != null)
212  data.SetValue("TableNames", tableNames.ToArray());
213  if (fromTables != null)
214  data.SetValue("FromTables", fromTables.ToArray());
215  if (joinParts != null)
216  data.SetValue("JoinParts", joinParts.ToArray());
217  }
218 
219  //public static void Serialize(FromClause clause, BinaryWriter writer) {
220  // var tableNamesCount = clause.tableNames.Count;
221  // writer.Write(tableNamesCount);
222  // for (int i = 0; i < tableNamesCount; i++) {
223  // writer.Write(clause.tableNames[0]);
224  // }
225 
226  // var tableCount = clause.fromTables.Count;
227  // writer.Write(tableCount);
228  // for (int i = 0; i < tableCount; i++) {
229  // FromTable.Serialize(clause.fromTables[i], writer);
230  // }
231 
232  // var joinCount = clause.joinParts.Count;
233  // writer.Write(joinCount);
234  // for (int i = 0; i < joinCount; i++) {
235  // JoinPart.Serialize(clause.joinParts[i], writer);
236  // }
237  //}
238 
239  //public static FromClause Deserialize(BinaryReader reader) {
240  // var fromClause = new FromClause();
241 
242  // var tableNameCount = reader.ReadInt32();
243 
244  // for (int i = 0; i < tableNameCount; i++) {
245  // fromClause.tableNames.Add(reader.ReadString());
246  // }
247 
248  // var tableCount = reader.ReadInt32();
249  // for (int i = 0; i < tableCount; i++) {
250  // fromClause.fromTables.Add(FromTable.Deserialize(reader));
251  // }
252 
253  // var joinCount = reader.ReadInt32();
254  // for (int i = 0; i < joinCount; i++) {
255  // fromClause.joinParts.Add(JoinPart.Deserialize(reader));
256  // }
257 
258  // return fromClause;
259  //}
260  }
261 }
void GetData(SerializeData data)
static ObjectName Parse(string s)
Parses the given string into a ObjectName object.
Definition: ObjectName.cs:139
JoinType
Enumerates the kind of group join in a selection query.
Definition: JoinType.cs:23
void AddTable(string alias, FromTable table)
Adds a table as source to the query with a given alias.
Definition: FromClause.cs:93
readonly List< JoinPart > joinParts
Definition: FromClause.cs:58
void Join(JoinType joinType, SqlExpression onExpression)
Sets a join between the last added table and the one that preceeds it.
Definition: FromClause.cs:154
void SetValue(string key, Type type, object value)
Describes the name of an object within a database.
Definition: ObjectName.cs:44
JoinPart GetJoinPart(int offset)
Gets the descriptor of the join at the given offset.
Definition: FromClause.cs:174
readonly List< string > tableNames
Definition: FromClause.cs:56
int tableKey
An id used for making unique names for anonymous inner selects.
Definition: FromClause.cs:63
void AddSubQuery(SqlQueryExpression subQuery)
Adds a sub-query expression as source of the query.
Definition: FromClause.cs:134
A container for the FROM clause of a select statement.
Definition: FromClause.cs:32
An interface used to prepare a SqlExpression object.
string UniqueKey
Gets or sets the unique key.
Definition: FromTable.cs:93
readonly List< FromTable > fromTables
Definition: FromClause.cs:57
object Prepare(IExpressionPreparer preparer)
Converts the underlying value of this instance into an object that can be evaluated by an expression...
void AddTable(string alias, string tableName)
Adds a simple table reference as the source of the query with a given alias.
Definition: FromClause.cs:116
void AddTable(string tableName)
Adds a simple table reference as the source of the query.
Definition: FromClause.cs:125
Describes a single table declaration in the from clause of a table expression (SELECT).
Definition: FromTable.cs:27
Defines the base class for instances that represent SQL expression tree nodes.
void AddSubQuery(string alias, SqlQueryExpression subQuery)
Adds a sub-query expression as source of the query.
Definition: FromClause.cs:145
A contract for objects that participate to a SqlExpression.Prepare phase of an expression evaluation...
Definition: IPreparable.cs:30