DeveelDB  20151217
complete SQL database system, primarly developed for .NET/Mono frameworks
QueryExtensions.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.Caching;
22 using Deveel.Data.Security;
23 using Deveel.Data.Services;
25 using Deveel.Data.Sql.Query;
26 using Deveel.Data.Sql.Schemas;
27 
28 namespace Deveel.Data.Sql.Tables {
29  public static partial class QueryExtensions {
30  public static ObjectName ResolveTableName(this IQuery query, ObjectName tableName) {
31  return query.Session.ResolveTableName(tableName);
32  }
33 
34  public static ObjectName ResolveTableName(this IQuery query, string name) {
35  var schema = query.CurrentSchema();
36  if (String.IsNullOrEmpty(schema))
37  throw new InvalidOperationException("Default schema not specified in the query.");
38 
39  var objSchemaName = query.ResolveSchemaName(schema);
40  if (objSchemaName == null)
41  throw new InvalidOperationException(
42  String.Format("The default schema of the session '{0}' is not defined in the database.", schema));
43 
44  var objName = ObjectName.Parse(name);
45  if (objName.Parent == null)
46  objName = new ObjectName(objSchemaName, objName.Name);
47 
48  return query.ResolveTableName(objName);
49  }
50 
51  public static bool TableExists(this IQuery query, ObjectName tableName) {
52  return query.ObjectExists(DbObjectType.Table, tableName);
53  }
54 
55  public static void CreateTable(this IQuery query, TableInfo tableInfo) {
56  CreateTable(query, tableInfo, false);
57  }
58 
59  public static void CreateTable(this IQuery query, TableInfo tableInfo, bool onlyIfNotExists) {
60  CreateTable(query, tableInfo, onlyIfNotExists, false);
61  }
62 
63  public static void CreateTable(this IQuery query, TableInfo tableInfo, bool onlyIfNotExists, bool temporary) {
64  if (tableInfo == null)
65  throw new ArgumentNullException("tableInfo");
66 
67  var tableName = tableInfo.TableName;
68 
69  if (!query.UserCanCreateTable(tableName))
70  throw new MissingPrivilegesException(query.User().Name, tableName, Privileges.Create);
71 
72  if (query.TableExists(tableName)) {
73  if (!onlyIfNotExists)
74  throw new InvalidOperationException(
75  String.Format("The table {0} already exists and the IF NOT EXISTS clause was not specified.", tableName));
76 
77  return;
78  }
79 
80  query.Session.CreateTable(tableInfo, temporary);
81 
82  using (var systemContext = query.Direct()) {
83  systemContext.GrantToUserOnTable(tableInfo.TableName, query.User().Name, Privileges.TableAll);
84  }
85  }
86 
87  public static ITableQueryInfo GetTableQueryInfo(this IQuery context, ObjectName tableName, ObjectName alias) {
88  return context.Session.GetTableQueryInfo(tableName, alias);
89  }
90 
91  internal static void CreateSystemTable(this IQuery query, TableInfo tableInfo) {
92  if (tableInfo == null)
93  throw new ArgumentNullException("tableInfo");
94 
95  var tableName = tableInfo.TableName;
96 
97  if (!query.UserCanCreateTable(tableName))
98  throw new MissingPrivilegesException(query.User().Name, tableName, Privileges.Create);
99 
100  query.Session.CreateTable(tableInfo, false);
101  }
102 
103  public static void DropTables(this IQuery query, IEnumerable<ObjectName> tableNames) {
104  DropTables(query, tableNames, false);
105  }
106 
107  public static void DropTables(this IQuery query, IEnumerable<ObjectName> tableNames, bool onlyIfExists) {
108  var tableNameList = tableNames.ToList();
109  foreach (var tableName in tableNameList) {
110  if (!query.UserCanDropObject(DbObjectType.Table, tableName))
111  throw new MissingPrivilegesException(query.UserName(), tableName, Privileges.Drop);
112  }
113 
114  // Check there are no referential links to any tables being dropped
115  foreach (var tableName in tableNameList) {
116  var refs = query.GetTableImportedForeignKeys(tableName);
117 
118  foreach (var reference in refs) {
119  // If the key table isn't being dropped then error
120  if (!tableNameList.Contains(reference.TableName)) {
122  String.Format("Constraint violation ({0}) dropping table '{1}' because of referential link from '{2}'",
123  reference.ConstraintName, tableName, reference.TableName));
124  }
125  }
126  }
127 
128  // If the 'only if exists' flag is false, we need to check tables to drop
129  // exist first.
130  if (!onlyIfExists) {
131  // For each table to drop.
132  foreach (var tableName in tableNameList) {
133  // If table doesn't exist, throw an error
134  if (!query.TableExists(tableName)) {
135  throw new InvalidOperationException(String.Format("The table '{0}' does not exist and cannot be dropped.",
136  tableName));
137  }
138  }
139  }
140 
141  foreach (var tname in tableNameList) {
142  // Does the table already exist?
143  if (query.TableExists(tname)) {
144  // Drop table in the transaction
145  query.DropObject(DbObjectType.Table, tname);
146 
147  // Revoke all the grants on the table
148  query.RevokeAllGrantsOnTable(tname);
149 
150  // Drop all constraints from the schema
151  query.DropAllTableConstraints(tname);
152  }
153  }
154  }
155 
156  public static void DropTable(this IQuery query, ObjectName tableName) {
157  DropTable(query, tableName, false);
158  }
159 
160  public static void DropTable(this IQuery query, ObjectName tableName, bool onlyIfExists) {
161  query.DropTables(new[] { tableName }, onlyIfExists);
162  }
163 
164  public static void AlterTable(this IQuery query, TableInfo tableInfo) {
165  query.AlterObject(tableInfo);
166  }
167 
168  private static ICache TableCache(this IQuery query) {
169  return query.Context.ResolveService<ICache>("TableCache");
170  }
171 
172  public static ITable GetTable(this IQuery query, ObjectName tableName) {
173  var table = query.GetCachedTable(tableName.FullName) as ITable;
174  if (table == null) {
175  table = query.Session.GetTable(tableName);
176  if (table != null) {
177  table = new UserContextTable(query, table);
178  query.CacheTable(tableName.FullName, table);
179  }
180  }
181 
182  return table;
183  }
184 
185  public static IMutableTable GetMutableTable(this IQuery query, ObjectName tableName) {
186  return query.GetTable(tableName) as IMutableTable;
187  }
188 
189  public static ITable GetCachedTable(this IQuery query, string cacheKey) {
190  var tableCache = query.TableCache();
191  if (tableCache == null)
192  return null;
193 
194  object obj;
195  if (!tableCache.TryGet(cacheKey, out obj))
196  return null;
197 
198  return obj as ITable;
199  }
200 
201  public static void CacheTable(this IQuery query, string cacheKey, ITable table) {
202  var tableCache = query.TableCache();
203  if (tableCache == null)
204  return;
205 
206  tableCache.Set(cacheKey, table);
207  }
208 
209  public static void ClearCachedTables(this IQuery query) {
210  var tableCache = query.TableCache();
211  if (tableCache == null)
212  return;
213 
214  tableCache.Clear();
215  }
216 
217  #region Constraints
218 
219  public static void AddPrimaryKey(this IQuery query, ObjectName tableName, string[] columnNames) {
220  AddPrimaryKey(query, tableName, columnNames, null);
221  }
222 
223  public static void AddPrimaryKey(this IQuery query, ObjectName tableName, string[] columnNames, string constraintName) {
224  if (!query.UserCanAlterTable(tableName))
225  throw new MissingPrivilegesException(query.UserName(), tableName, Privileges.Alter);
226 
227  query.Session.AddPrimaryKey(tableName, columnNames, ConstraintDeferrability.InitiallyImmediate, constraintName);
228  }
229 
230  public static void AddPrimaryKey(this IQuery query, ObjectName tableName, string columnName) {
231  AddPrimaryKey(query, tableName, columnName, null);
232  }
233 
234  public static void AddPrimaryKey(this IQuery query, ObjectName tableName, string columnName, string constraintName) {
235  query.AddPrimaryKey(tableName, new[] { columnName }, constraintName);
236  }
237 
238  public static void AddForeignKey(this IQuery query, ObjectName table, string[] columns, ObjectName refTable,
239  string[] refColumns, ForeignKeyAction deleteRule, ForeignKeyAction updateRule,
240  String constraintName) {
241  AddForeignKey(query, table, columns, refTable, refColumns, deleteRule, updateRule, ConstraintDeferrability.InitiallyImmediate, constraintName);
242  }
243 
244  public static void AddForeignKey(this IQuery query, ObjectName table, string[] columns, ObjectName refTable,
245  string[] refColumns, ForeignKeyAction deleteRule, ForeignKeyAction updateRule, ConstraintDeferrability deferred,
246  String constraintName) {
247  if (!query.UserCanAlterTable(table))
248  throw new MissingPrivilegesException(query.UserName(), table, Privileges.Alter);
249  if (!query.UserCanReferenceTable(refTable))
250  throw new MissingPrivilegesException(query.UserName(), refTable, Privileges.References);
251 
252  query.Session.AddForeignKey(table, columns, refTable, refColumns, deleteRule, updateRule, deferred, constraintName);
253  }
254 
255  public static void AddUniqueKey(this IQuery query, ObjectName tableName, string[] columns) {
256  AddUniqueKey(query, tableName, columns, null);
257  }
258 
259  public static void AddUniqueKey(this IQuery query, ObjectName tableName, string[] columns, string constraintName) {
260  AddUniqueKey(query, tableName, columns, ConstraintDeferrability.InitiallyImmediate, constraintName);
261  }
262 
263  public static void AddUniqueKey(this IQuery query, ObjectName tableName, string[] columns,
264  ConstraintDeferrability deferrability) {
265  AddUniqueKey(query, tableName, columns, deferrability, null);
266  }
267 
268  public static void AddUniqueKey(this IQuery query, ObjectName tableName, string[] columns,
269  ConstraintDeferrability deferrability, string constraintName) {
270  if (!query.UserCanAlterTable(tableName))
271  throw new MissingPrivilegesException(query.UserName(), tableName, Privileges.Alter);
272 
273  query.Session.AddUniqueKey(tableName, columns, deferrability, constraintName);
274  }
275 
276  public static void AddCheck(this IQuery query, ObjectName tableName, SqlExpression expression, string constraintName) {
277  AddCheck(query, tableName, expression, ConstraintDeferrability.InitiallyImmediate, constraintName);
278  }
279 
280  public static void AddCheck(this IQuery query, ObjectName tableName, SqlExpression expression, ConstraintDeferrability deferred, string constraintName) {
281  query.Session.AddCheck(tableName, expression, deferred, constraintName);
282  }
283 
284  public static void DropAllTableConstraints(this IQuery query, ObjectName tableName) {
285  query.Session.DropAllTableConstraints(tableName);
286  }
287 
288  public static int DropConstraint(this IQuery query, ObjectName tableName, string constraintName) {
289  return query.Session.DropTableConstraint(tableName, constraintName);
290  }
291 
292  public static void AddConstraint(this IQuery query, ObjectName tableName, ConstraintInfo constraintInfo) {
293  if (constraintInfo.ConstraintType == ConstraintType.PrimaryKey) {
294  var columnNames = constraintInfo.ColumnNames;
295  if (columnNames.Length > 1)
296  throw new ArgumentException();
297 
298  query.AddPrimaryKey(tableName, columnNames[0], constraintInfo.ConstraintName);
299  } else if (constraintInfo.ConstraintType == ConstraintType.Unique) {
300  query.AddUniqueKey(tableName, constraintInfo.ColumnNames, constraintInfo.ConstraintName);
301  } else if (constraintInfo.ConstraintType == ConstraintType.Check) {
302  query.AddCheck(tableName, constraintInfo.CheckExpression, constraintInfo.ConstraintName);
303  } else if (constraintInfo.ConstraintType == ConstraintType.ForeignKey) {
304  query.AddForeignKey(tableName, constraintInfo.ColumnNames, constraintInfo.ForeignTable,
305  constraintInfo.ForeignColumnNames, constraintInfo.OnDelete, constraintInfo.OnUpdate, constraintInfo.ConstraintName);
306  }
307  }
308 
309  public static bool DropPrimaryKey(this IQuery query, ObjectName tableName, string constraintName) {
310  return query.Session.DropTablePrimaryKey(tableName, constraintName);
311  }
312 
313  public static void CheckConstraints(this IQuery query, ObjectName tableName) {
314  query.Session.CheckConstraintViolations(tableName);
315  }
316 
317  public static ConstraintInfo[] GetTableCheckExpressions(this IQuery query, ObjectName tableName) {
318  return query.Session.QueryTableCheckExpressions(tableName);
319  }
320 
321  public static ConstraintInfo[] GetTableImportedForeignKeys(this IQuery query, ObjectName tableName) {
322  return query.Session.QueryTableImportedForeignKeys(tableName);
323  }
324 
325  public static ConstraintInfo[] GetTableForeignKeys(this IQuery query, ObjectName tableName) {
326  return query.Session.QueryTableForeignKeys(tableName);
327  }
328 
329  public static ConstraintInfo GetTablePrimaryKey(this IQuery query, ObjectName tableName) {
330  return query.Session.QueryTablePrimaryKey(tableName);
331  }
332 
333  public static ConstraintInfo[] GetTableUniqueKeys(this IQuery query, ObjectName tableName) {
334  return query.Session.QueryTableUniqueKeys(tableName);
335  }
336 
337  #endregion
338 
339  }
340 }
static void DropTables(this IQuery query, IEnumerable< ObjectName > tableNames, bool onlyIfExists)
static void AddConstraint(this IQuery query, ObjectName tableName, ConstraintInfo constraintInfo)
static void AddPrimaryKey(this IQuery query, ObjectName tableName, string columnName, string constraintName)
static ConstraintInfo[] GetTableUniqueKeys(this IQuery query, ObjectName tableName)
Defines the contract to access the data contained into a table of a database.
Definition: ITable.cs:40
Enumerates a known set of codes in a SQL Model
A wrapper around a table that fires triggers on table events.
static bool TableExists(this IQuery query, ObjectName tableName)
static ObjectName Parse(string s)
Parses the given string into a ObjectName object.
Definition: ObjectName.cs:139
A database exception that represents a constraint violation.
static void AddCheck(this IQuery query, ObjectName tableName, SqlExpression expression, string constraintName)
static void AlterTable(this IQuery query, TableInfo tableInfo)
static void DropTable(this IQuery query, ObjectName tableName, bool onlyIfExists)
static void AddCheck(this IQuery query, ObjectName tableName, SqlExpression expression, ConstraintDeferrability deferred, string constraintName)
static ConstraintInfo[] GetTableForeignKeys(this IQuery query, ObjectName tableName)
static void AddUniqueKey(this IQuery query, ObjectName tableName, string[] columns, ConstraintDeferrability deferrability, string constraintName)
static void AddUniqueKey(this IQuery query, ObjectName tableName, string[] columns)
Describes the name of an object within a database.
Definition: ObjectName.cs:44
ConstraintDeferrability
The type of deferrance of a constraint.
static void AddForeignKey(this IQuery query, ObjectName table, string[] columns, ObjectName refTable, string[] refColumns, ForeignKeyAction deleteRule, ForeignKeyAction updateRule, String constraintName)
static void DropTable(this IQuery query, ObjectName tableName)
ObjectName TableName
Gets the fully qualified name of the table that is ensured to be unique within the system...
Definition: TableInfo.cs:97
ForeignKeyAction
Enumerates the foreign key referential trigger actions.
static void ClearCachedTables(this IQuery query)
static void CreateTable(this IQuery query, TableInfo tableInfo, bool onlyIfNotExists, bool temporary)
ConstraintType
An enumeration of all the supported kinds of constraints within a table or a schema.
static IMutableTable GetMutableTable(this IQuery query, ObjectName tableName)
static ObjectName ResolveTableName(this IQuery query, string name)
static ConstraintInfo GetTablePrimaryKey(this IQuery query, ObjectName tableName)
ISession Session
Definition: IQuery.cs:23
static ConstraintInfo[] GetTableCheckExpressions(this IQuery query, ObjectName tableName)
static ITable GetTable(this IQuery query, ObjectName tableName)
static void CheckConstraints(this IQuery query, ObjectName tableName)
string FullName
Gets the full reference name formatted.
Definition: ObjectName.cs:114
static void DropTables(this IQuery query, IEnumerable< ObjectName > tableNames)
static ITableQueryInfo GetTableQueryInfo(this IQuery context, ObjectName tableName, ObjectName alias)
static void CreateTable(this IQuery query, TableInfo tableInfo, bool onlyIfNotExists)
const int DropTableViolation
Tried to drop a table that is referenced by another source.
static void CreateTable(this IQuery query, TableInfo tableInfo)
static ITable GetCachedTable(this IQuery query, string cacheKey)
Provides a contract to access a caching system.
Definition: ICache.cs:25
static void AddUniqueKey(this IQuery query, ObjectName tableName, string[] columns, ConstraintDeferrability deferrability)
static void CreateSystemTable(this IQuery query, TableInfo tableInfo)
static ICache TableCache(this IQuery query)
Defines the base class for instances that represent SQL expression tree nodes.
static int DropConstraint(this IQuery query, ObjectName tableName, string constraintName)
static void CacheTable(this IQuery query, string cacheKey, ITable table)
DbObjectType
The kind of objects that can be handled by a database system and its managers
Definition: DbObjectType.cs:27
static ConstraintInfo[] GetTableImportedForeignKeys(this IQuery query, ObjectName tableName)
static void AddForeignKey(this IQuery query, ObjectName table, string[] columns, ObjectName refTable, string[] refColumns, ForeignKeyAction deleteRule, ForeignKeyAction updateRule, ConstraintDeferrability deferred, String constraintName)
Defines the metadata properties of a table existing within a database.
Definition: TableInfo.cs:41
static void DropAllTableConstraints(this IQuery query, ObjectName tableName)
static ObjectName ResolveTableName(this IQuery query, ObjectName tableName)
new IQueryContext Context
Definition: IQuery.cs:21
An interface that defines contracts to alter the contents of a table.
static void AddPrimaryKey(this IQuery query, ObjectName tableName, string[] columnNames, string constraintName)
static void AddPrimaryKey(this IQuery query, ObjectName tableName, string[] columnNames)
static void AddUniqueKey(this IQuery query, ObjectName tableName, string[] columns, string constraintName)
static bool DropPrimaryKey(this IQuery query, ObjectName tableName, string constraintName)
static void AddPrimaryKey(this IQuery query, ObjectName tableName, string columnName)