DeveelDB  20151217
complete SQL database system, primarly developed for .NET/Mono frameworks
TableConstraintNode.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 
22 using Deveel.Data.Sql.Tables;
23 
24 namespace Deveel.Data.Sql.Parser {
26  private bool notSeen;
27  private readonly IList<string> columns;
28  private readonly IList<string> refColumns;
29 
30  internal TableConstraintNode() {
31  columns = new List<string>();
32  refColumns = new List<string>();
33  }
34 
35  public string ConstraintName { get; private set; }
36 
37  public string ConstraintType { get; private set; }
38 
39  public IEnumerable<string> Columns {
40  get { return columns.AsEnumerable(); }
41  }
42 
43  public IExpressionNode CheckExpression { get; private set; }
44 
45  public ObjectNameNode ReferencedTableName { get; private set; }
46 
47  public IEnumerable<string> ReferencedColumns {
48  get { return refColumns.AsEnumerable(); }
49  }
50 
51  public string OnUpdateAction { get; private set; }
52 
53  public string OnDeleteAction { get; private set; }
54 
55  protected override ISqlNode OnChildNode(ISqlNode node) {
56  if (node.NodeName == "table_constraint_name_opt") {
57  ReadConstraintName(node.ChildNodes);
58  } else if (node.NodeName == "def_table_constraint") {
59  ReadConstraintDefinition(node);
60  }
61 
62  return base.OnChildNode(node);
63  }
64 
65  private void ReadConstraintDefinition(ISqlNode node) {
66  foreach (var childNode in node.ChildNodes) {
67  if (childNode is SqlKeyNode) {
68  var keyNode = (SqlKeyNode) childNode;
69  if (String.Equals(keyNode.Text, "NULL", StringComparison.OrdinalIgnoreCase)) {
70  if (notSeen) {
71  ConstraintType = "NOT NULL";
72  } else {
73  ConstraintType = "NULL";
74  }
75  } else if (String.Equals(keyNode.Text, "NOT", StringComparison.OrdinalIgnoreCase)) {
76  notSeen = true;
77  } else if (String.Equals(keyNode.Text, "REFERENCES", StringComparison.OrdinalIgnoreCase)) {
79  } else if (String.Equals(keyNode.Text, "CHECK", StringComparison.OrdinalIgnoreCase)) {
81  } else if (String.Equals(keyNode.Text, "PRIMARY", StringComparison.OrdinalIgnoreCase)) {
83  } else if (String.Equals(keyNode.Text, "UNIQUE", StringComparison.OrdinalIgnoreCase)) {
85  }
86  } else if (childNode.NodeName == "column_list") {
87  ReadColumnList(childNode.ChildNodes);
88  }
89  }
90  }
91 
92  private void ReadConstraintName(IEnumerable<ISqlNode> nodes) {
93  foreach (var node in nodes) {
94  if (node is IdentifierNode) {
95  ConstraintName = ((IdentifierNode) node).Text;
96  } else {
97  ReadConstraintName(node.ChildNodes);
98  }
99  }
100  }
101 
102  private void ReadColumnList(IEnumerable<ISqlNode> nodes) {
103  foreach (var node in nodes) {
104  if (node is IdentifierNode) {
105  columns.Add(((IdentifierNode) node).Text);
106  } else {
107  ReadColumnList(node.ChildNodes);
108  }
109  }
110  }
111 
113  if (String.Equals(ConstraintTypeNames.Check, ConstraintType, StringComparison.OrdinalIgnoreCase)) {
114  var exp = ExpressionBuilder.Build(CheckExpression);
115  return new SqlTableConstraint(ConstraintName, Tables.ConstraintType.Check, Columns.ToArray()) {
116  CheckExpression = exp
117  };
118  }
119  if (String.Equals(ConstraintTypeNames.PrimaryKey, ConstraintType, StringComparison.OrdinalIgnoreCase))
120  return SqlTableConstraint.PrimaryKey(ConstraintName, Columns.ToArray());
121  if (String.Equals(ConstraintTypeNames.UniqueKey, ConstraintType, StringComparison.OrdinalIgnoreCase))
122  return SqlTableConstraint.UniqueKey(ConstraintName, Columns.ToArray());
123  if (String.Equals(ConstraintTypeNames.ForeignKey, ConstraintType, StringComparison.OrdinalIgnoreCase)) {
124  var fTable = ReferencedTableName.Name;
125  var fColumns = ReferencedColumns;
126  var onDelete = ForeignKeyAction.NoAction;
127  var onUpdate = ForeignKeyAction.NoAction;
128 
129  if (!String.IsNullOrEmpty(OnDeleteAction))
130  onDelete = StatementBuilder.GetForeignKeyAction(OnDeleteAction);
131  if (!String.IsNullOrEmpty(OnUpdateAction))
132  onUpdate = StatementBuilder.GetForeignKeyAction(OnUpdateAction);
133 
134  var fkey = SqlTableConstraint.ForeignKey(ConstraintName, Columns.ToArray(), fTable,
135  fColumns.ToArray(), onDelete, onUpdate);
136 
137  return fkey;
138  }
139 
140  throw new NotSupportedException();
141  }
142  }
143 }
void ReadConstraintName(IEnumerable< ISqlNode > nodes)
This is a simple identifier within a SQL grammar.
Defines the contract for nodes in an AST model for a SQL grammar analysis and parsing.
Definition: ISqlNode.cs:25
Represents a keyword found during the compilation of a source text.
Definition: SqlKeyNode.cs:25
Represents a composed name for an object within the system.
string NodeName
Gets the name of the node analyzed from the parser.
Definition: ISqlNode.cs:29
static SqlExpression Build(IExpressionNode node)
static SqlTableConstraint PrimaryKey(string constraintName, string[] columns)
static ForeignKeyAction GetForeignKeyAction(string actionName)
override ISqlNode OnChildNode(ISqlNode node)
During the initialization of the node from the parser, this method is called for every child node add...
ForeignKeyAction
Enumerates the foreign key referential trigger actions.
ConstraintType
An enumeration of all the supported kinds of constraints within a table or a schema.
static SqlTableConstraint UniqueKey(string constraintName, string[] columns)
IEnumerable< ISqlNode > ChildNodes
Gets a read-only enumeration of the children nodes, if any.
Definition: ISqlNode.cs:39
void ReadColumnList(IEnumerable< ISqlNode > nodes)
This interface acts like a marker that indicates if a ISqlNode represents a SQL expression.
static SqlTableConstraint ForeignKey(string constraintName, string[] columns, string refTable, string[] refcolumns, ForeignKeyAction onDelete, ForeignKeyAction onUpdate)
The default implementation of ISqlNode, that is a node in the text analysis parsing of SQL commands...
Definition: SqlNode.cs:32