DeveelDB  20151217
complete SQL database system, primarly developed for .NET/Mono frameworks
CreateTableStatement.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.Security;
23 using Deveel.Data.Sql.Tables;
24 
25 namespace Deveel.Data.Sql.Statements {
35  public CreateTableStatement(string tableName, IEnumerable<SqlTableColumn> columns) {
36  TableName = tableName;
37  Columns = new List<SqlTableColumn>();
38  if (columns != null) {
39  foreach (var column in columns) {
40  Columns.Add(column);
41  }
42  }
43  }
44 
45  public string TableName { get; private set; }
46 
47  public IList<SqlTableColumn> Columns { get; private set; }
48 
49  public bool IfNotExists { get; set; }
50 
51  public bool Temporary { get; set; }
52 
54  var tableInfo = CreateTableInfo(context);
55 
56  return new Prepared(tableInfo, IfNotExists, Temporary);
57  }
58 
59  private TableInfo CreateTableInfo(IRequest context) {
60  var tableName = context.Query.ResolveTableName(TableName);
61 
62  var idColumnCount = Columns.Count(x => x.IsIdentity);
63  if (idColumnCount > 1)
64  throw new InvalidOperationException("More than one IDENTITY column specified.");
65 
66  bool ignoreCase = context.Query.IgnoreIdentifiersCase();
67  var columnChecker = new TableColumnChecker(Columns, ignoreCase);
68 
69 
70  var tableInfo = new TableInfo(tableName);
71 
72  foreach (var column in Columns) {
73  var columnInfo = CreateColumnInfo(tableName.Name, column, columnChecker);
74  tableInfo.AddColumn(columnInfo);
75  }
76 
77  return tableInfo;
78  }
79 
80  private ColumnInfo CreateColumnInfo(string tableName, SqlTableColumn column, TableColumnChecker columnChecker) {
81  var expression = column.DefaultExpression;
82 
83  if (column.IsIdentity && expression != null)
84  throw new InvalidOperationException(String.Format("Identity column '{0}' cannot define a DEFAULT expression.", column.ColumnName));
85 
86  if (expression != null)
87  expression = columnChecker.CheckExpression(expression);
88 
89 
90  var columnName = columnChecker.StripTableName(tableName, column.ColumnName);
91 
92  return new ColumnInfo(columnName, column.ColumnType) {
93  DefaultExpression = expression,
94  IsNotNull = column.IsNotNull
95  };
96  }
97 
98  #region Prepared
99 
100  [Serializable]
101  internal class Prepared : SqlStatement {
102  private Prepared(ObjectData data) {
103  TableInfo = data.GetValue<TableInfo>("TableInfo");
104  Temporary = data.GetBoolean("Temporary");
105  IfNotExists = data.GetBoolean("IfNotExists");
106  }
107 
108  public TableInfo TableInfo { get; private set; }
109 
110  public bool Temporary { get; private set; }
111 
112  public bool IfNotExists { get; private set; }
113 
114  internal Prepared(TableInfo tableInfo, bool ifNotExists, bool temporary) {
115  TableInfo = tableInfo;
116  IfNotExists = ifNotExists;
117  Temporary = temporary;
118  }
119 
120  protected override void ExecuteStatement(ExecutionContext context) {
121  try {
122  context.Request.Query.CreateTable(TableInfo, IfNotExists, Temporary);
123  } catch (SecurityException ex) {
124  throw new StatementException(String.Format("A security error occurred while creating the table '{0}'.", TableInfo.TableName), ex);
125  }
126  }
127 
128  protected override void GetData(SerializeData data) {
129  data.SetValue("TableInfo", typeof(TableInfo), TableInfo);
130  data.SetValue("Temporary", Temporary);
131  data.SetValue("IfNotExists", IfNotExists);
132  }
133  }
134 
135  #endregion
136 
137  #region TableColumnChecker
138 
140  private readonly IEnumerable<SqlTableColumn> columns;
141  private readonly bool ignoreCase;
142 
143  public TableColumnChecker(IEnumerable<SqlTableColumn> columns, bool ignoreCase) {
144  this.columns = columns;
145  this.ignoreCase = ignoreCase;
146  }
147 
148  public override string ResolveColumnName(string columnName) {
149  var comparison = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
150  string foundColumn = null;
151 
152  foreach (var columnInfo in columns) {
153  if (foundColumn != null)
154  throw new InvalidOperationException(String.Format("Column name '{0}' caused an ambiguous match in table.", columnName));
155 
156  if (String.Equals(columnInfo.ColumnName, columnName, comparison))
157  foundColumn = columnInfo.ColumnName;
158  }
159 
160  return foundColumn;
161  }
162  }
163 
164  #endregion
165 
166  #region PreparedSerializer
167 
168  //internal class PreparedSerializer : ObjectBinarySerializer<Prepared> {
169  // public override void Serialize(Prepared obj, BinaryWriter writer) {
170  // TableInfo.Serialize(obj.TableInfo, writer);
171  // writer.Write(obj.Temporary);
172  // writer.Write(obj.IfNotExists);
173  // }
174 
175  // public override Prepared Deserialize(BinaryReader reader) {
176  // // TODO: Type Resolver!!!
177  // var tableInfo = TableInfo.Deserialize(reader, null);
178  // var temporary = reader.ReadBoolean();
179  // var ifNotExists = reader.ReadBoolean();
180 
181  // return new Prepared(tableInfo, ifNotExists, temporary);
182  // }
183  //}
184 
185  #endregion
186  }
187 }
Defines the metadata properties of a column within a table of a database.
Definition: ColumnInfo.cs:36
TableColumnChecker(IEnumerable< SqlTableColumn > columns, bool ignoreCase)
The statement object used to create a table in a database.
string StripTableName(string tableDomain, string column)
ColumnInfo CreateColumnInfo(string tableName, SqlTableColumn column, TableColumnChecker columnChecker)
void SetValue(string key, Type type, object value)
override void ExecuteStatement(ExecutionContext context)
ObjectName TableName
Gets the fully qualified name of the table that is ensured to be unique within the system...
Definition: TableInfo.cs:97
Represents the foundation class of SQL statements to be executed.
Definition: SqlStatement.cs:32
CreateTableStatement(string tableName, IEnumerable< SqlTableColumn > columns)
SqlExpression CheckExpression(SqlExpression expression)
Defines the metadata properties of a table existing within a database.
Definition: TableInfo.cs:41
Prepared(TableInfo tableInfo, bool ifNotExists, bool temporary)