DeveelDB  20151217
complete SQL database system, primarly developed for .NET/Mono frameworks
FromTableDirectSource.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.Linq;
19 
20 using Deveel.Data.Sql.Tables;
21 
22 namespace Deveel.Data.Sql.Query {
31  private readonly ITableQueryInfo tableQuery;
32  private readonly TableInfo tableInfo;
33 
42  public FromTableDirectSource(bool caseInsensitive, ITableQueryInfo tableQuery, string uniqueName, ObjectName givenName, ObjectName rootName) {
43  this.UniqueName = uniqueName;
44  tableInfo = tableQuery.TableInfo;
45  RootTableName = rootName;
46  if (givenName != null) {
47  GivenTableName = givenName;
48  } else {
49  GivenTableName = rootName;
50  }
51 
52  IgnoreCase = caseInsensitive;
53  this.tableQuery = tableQuery;
54  }
55 
56  public bool IgnoreCase { get; private set; }
57 
58  public ObjectName GivenTableName { get; private set; }
59 
60  public ObjectName RootTableName { get; private set; }
61 
62  public IQueryPlanNode QueryPlan {
63  get { return tableQuery.QueryPlanNode; }
64  }
65 
66  public string UniqueName { get; private set; }
67 
68  public ObjectName[] ColumnNames {
69  get {
70  int colCount = tableInfo.ColumnCount;
71  var vars = new ObjectName[colCount];
72  for (int i = 0; i < colCount; ++i) {
73  vars[i] = new ObjectName(GivenTableName, tableInfo[i].ColumnName);
74  }
75  return vars;
76  }
77  }
78 
79  private bool StringCompare(string str1, string str2) {
80  var comparison = IgnoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
81  return String.Equals(str1, str2, comparison);
82  }
83 
84 
85  public bool MatchesReference(string catalog, string schema, string table) {
86  var schemaName = GivenTableName.Parent;
87  var catalogName = schemaName == null ? null : schemaName.Parent;
88 
89  // Does this table name represent the correct schema?
90  var givenSchema = schemaName != null ? schemaName.Name : null;
91  if (schema != null && !StringCompare(schema, givenSchema)) {
92  // If schema is present and we can't resolve to this schema then false
93  return false;
94  }
95 
96  var givenCatalog = catalogName != null ? catalogName.Name : null;
97  if (catalog != null && !StringCompare(catalog, givenCatalog))
98  return false;
99 
100  if (table != null && !StringCompare(table, GivenTableName.Name)) {
101  // If table name is present and we can't resolve to this table name
102  // then return false
103  return false;
104  }
105 
106  // Match was successful,
107  return true;
108  }
109 
110  public int ResolveColumnCount(string catalog, string schema, string table, string column) {
111  // NOTE: With this type, we can only ever return either 1 or 0 because
112  // it's impossible to have an ambiguous reference
113 
114  var schemaName = GivenTableName.Parent;
115  var catalogName = schemaName == null ? null : schemaName.Parent;
116 
117  var givenCatalog = catalogName != null ? catalogName.Name : null;
118  if (catalog != null && !StringCompare(catalog, givenCatalog))
119  return 0;
120 
121  var givenSchema = schemaName != null ? schemaName.Name : null;
122  if (schema != null && !StringCompare(schema, givenSchema))
123  return 0;
124 
125  if (table != null && !StringCompare(table, GivenTableName.Name)) {
126  return 0;
127  }
128 
129  if (column != null) {
130  // TODO: the case-insensitive search in TableInfo
131  if (!IgnoreCase) {
132  // Can we resolve the column in this table?
133  int i = tableInfo.IndexOfColumn(column);
134  // If i doesn't equal -1 then we've found our column
135  return i == -1 ? 0 : 1;
136  }
137 
138  return tableInfo.Count(columnInfo => StringCompare(columnInfo.ColumnName, column));
139  }
140 
141  // Return the column count
142  return tableInfo.ColumnCount;
143  }
144 
145  public ObjectName ResolveColumn(string catalog, string schema, string table, string column) {
146  var schemaName = GivenTableName.Parent;
147  var catalogName = schemaName == null ? null : schemaName.Parent;
148 
149  var givenCatalog = catalogName != null ? catalogName.Name : null;
150  if (catalog != null && !StringCompare(catalog, givenCatalog))
151  throw new InvalidOperationException("Incorrect catalog.");
152 
153  // Does this table name represent the correct schema?
154  var givenSchema = GivenTableName.Parent != null ? GivenTableName.Parent.Name : null;
155  if (schema != null && !StringCompare(schema, givenSchema))
156  // If schema is present and we can't resolve to this schema
157  throw new InvalidOperationException("Incorrect schema.");
158 
159  if (table != null && !StringCompare(table, GivenTableName.Name))
160  // If table name is present and we can't resolve to this table name
161  throw new InvalidOperationException("Incorrect table.");
162 
163  if (column != null) {
164  if (!IgnoreCase) {
165  // Can we resolve the column in this table?
166  int i = tableInfo.IndexOfColumn(column);
167  if (i == -1)
168  throw new InvalidOperationException("Could not resolve '" + column + "'");
169 
170  return new ObjectName(GivenTableName, column);
171  }
172 
173  // Case insensitive search (this is slower than case sensitive).
174  var columnName =
175  tableInfo.Where(x => StringCompare(x.ColumnName, column))
176  .Select(x => x.ColumnName)
177  .FirstOrDefault();
178 
179  if (String.IsNullOrEmpty(columnName))
180  throw new InvalidOperationException(String.Format("Could not resolve column '{0}' within the table '{1}'.", column,
181  GivenTableName));
182 
183  return new ObjectName(GivenTableName, columnName);
184  }
185 
186  // Return the first column in the table
187  return new ObjectName(GivenTableName, tableInfo[0].ColumnName);
188  }
189  }
190 }
bool StringCompare(string str1, string str2)
A query to the database to select data from a set of tables and columns.
A single table resource item in a query which handles the behaviour of resolving references to column...
Describes the name of an object within a database.
Definition: ObjectName.cs:44
ObjectName ResolveColumn(string catalog, string schema, string table, string column)
Resolves a variable within the current source.
FromTableDirectSource(bool caseInsensitive, ITableQueryInfo tableQuery, string uniqueName, ObjectName givenName, ObjectName rootName)
Constructs the source.
A node element of a query plan tree. /summary>
TableInfo TableInfo
Gets a read-only TableInfo that describes the columns in this table source, and the name of the table...
ObjectName Parent
Gets the parent reference of the current one, if any or null if none.
Definition: ObjectName.cs:99
string Name
Gets the name of the object being referenced.
Definition: ObjectName.cs:108
bool MatchesReference(string catalog, string schema, string table)
Checks if the table matches the given catalog, schema and table.
int ResolveColumnCount(string catalog, string schema, string table, string column)
Returns the number of instances we can resolve the given catalog, schema, table and column name to a ...
Defines the metadata properties of a table existing within a database.
Definition: TableInfo.cs:41
An implementation of IFromTableSource that wraps around a ObjectName/ITable object.