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