DeveelDB  20151217
complete SQL database system, primarly developed for .NET/Mono frameworks
ColumnChecker.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.Linq;
20 
21 using Deveel.Data;
23 using Deveel.Data.Sql.Query;
24 using Deveel.Data.Sql.Tables;
25 
26 namespace Deveel.Data.Sql.Statements {
27  abstract class ColumnChecker {
28  public string StripTableName(string tableDomain, string column) {
29  var index = column.IndexOf('.');
30 
31  if (index != -1) {
32  var columnPrefix = column.Substring(0, index);
33  if (!columnPrefix.Equals(tableDomain))
34  throw new InvalidOperationException(String.Format("Column '{0}' is not within the expected table'{1}'",
35  column, tableDomain));
36 
37  column = column.Substring(index + 1);
38  }
39 
40  return column;
41  }
42 
43  public IEnumerable<string> StripColumnList(string tableDomain, IEnumerable<string> columnList) {
44  return columnList.Select(x => StripTableName(tableDomain, x));
45  }
46 
47  public abstract string ResolveColumnName(string columnName);
48 
50  var expChecker = new ExpressionChecker(this);
51  return expChecker.Visit(expression);
52  }
53 
54  public IEnumerable<string> CheckColumns(IEnumerable<string> columnNames) {
55  var result = new List<string>();
56 
57  foreach (var columnName in columnNames) {
58  var resolved = ResolveColumnName(columnName);
59  if (resolved == null)
60  throw new InvalidOperationException(String.Format("Column '{0}' not found in table.", columnName));
61 
62  result.Add(resolved);
63  }
64 
65  return result.ToArray();
66  }
67 
68  public static ColumnChecker Default(IRequest context, ObjectName tableName) {
69  var table = context.Query.GetTable(tableName);
70  if (table == null)
71  throw new InvalidOperationException(String.Format("Table '{0}' not found in the context.", tableName));
72 
73  var tableInfo = table.TableInfo;
74  var ignoreCase = context.Query.IgnoreIdentifiersCase();
75 
76  return new DefaultChecker(tableInfo, ignoreCase);
77  }
78 
79  #region DefaultChecker
80 
82  private readonly TableInfo tableInfo;
83  private readonly bool ignoreCase;
84 
85  public DefaultChecker(TableInfo tableInfo, bool ignoreCase) {
86  this.tableInfo = tableInfo;
87  this.ignoreCase = ignoreCase;
88  }
89 
90  public override string ResolveColumnName(string columnName) {
91  var comparison = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
92  string foundColumn = null;
93 
94  foreach (var columnInfo in tableInfo) {
95  if (foundColumn != null)
96  throw new InvalidOperationException(String.Format("Column name '{0}' caused an ambiguous match in table.", columnName));
97 
98  if (String.Equals(columnInfo.ColumnName, columnName, comparison))
99  foundColumn = columnInfo.ColumnName;
100  }
101 
102  return foundColumn;
103  }
104  }
105 
106  #endregion
107 
108  #region ExpressionChecker
109 
111  private readonly ColumnChecker checker;
112 
114  this.checker = checker;
115  }
116 
118  var refName = reference.ReferenceName;
119  var origColumn = refName.Name;
120  var resolvedColumn = checker.ResolveColumnName(origColumn);
121  if (resolvedColumn == null)
122  throw new InvalidOperationException(String.Format("Column '{0} not found in table.", origColumn));
123 
124  if (!origColumn.Equals(resolvedColumn))
125  refName = new ObjectName(refName.Parent, resolvedColumn);
126 
127  return SqlExpression.Reference(refName);
128  }
129 
130  public override SqlExpression VisitQuery(SqlQueryExpression query) {
131  throw new InvalidOperationException("Sub-queries are not permitted in a CHECK expression.");
132  }
133  }
134 
135  #endregion
136  }
137 }
ObjectName ReferenceName
Gets the name of the object referenced by the expression.
An expression that references an object within a context.
IEnumerable< string > CheckColumns(IEnumerable< string > columnNames)
string StripTableName(string tableDomain, string column)
Describes the name of an object within a database.
Definition: ObjectName.cs:44
override string ResolveColumnName(string columnName)
override SqlExpression VisitQuery(SqlQueryExpression query)
DefaultChecker(TableInfo tableInfo, bool ignoreCase)
IEnumerable< string > StripColumnList(string tableDomain, IEnumerable< string > columnList)
static ColumnChecker Default(IRequest context, ObjectName tableName)
string Name
Gets the name of the object being referenced.
Definition: ObjectName.cs:108
static SqlReferenceExpression Reference(ObjectName objectName)
SqlExpression CheckExpression(SqlExpression expression)
Defines the base class for instances that represent SQL expression tree nodes.
override SqlExpression VisitReference(SqlReferenceExpression reference)
Defines the metadata properties of a table existing within a database.
Definition: TableInfo.cs:41