1 | /* |
2 | * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0, |
3 | * and the EPL 1.0 (http://h2database.com/html/license.html). |
4 | * Initial Developer: H2 Group |
5 | */ |
6 | package org.h2.constraint; |
7 | |
8 | import java.util.HashSet; |
9 | import org.h2.engine.DbObject; |
10 | import org.h2.engine.Session; |
11 | import org.h2.expression.ExpressionVisitor; |
12 | import org.h2.index.Index; |
13 | import org.h2.message.DbException; |
14 | import org.h2.message.Trace; |
15 | import org.h2.result.Row; |
16 | import org.h2.schema.Schema; |
17 | import org.h2.schema.SchemaObjectBase; |
18 | import org.h2.table.Column; |
19 | import org.h2.table.Table; |
20 | |
21 | /** |
22 | * The base class for constraint checking. |
23 | */ |
24 | public abstract class Constraint extends SchemaObjectBase implements |
25 | Comparable<Constraint> { |
26 | |
27 | /** |
28 | * The constraint type name for check constraints. |
29 | */ |
30 | public static final String CHECK = "CHECK"; |
31 | |
32 | /** |
33 | * The constraint type name for referential constraints. |
34 | */ |
35 | public static final String REFERENTIAL = "REFERENTIAL"; |
36 | |
37 | /** |
38 | * The constraint type name for unique constraints. |
39 | */ |
40 | public static final String UNIQUE = "UNIQUE"; |
41 | |
42 | /** |
43 | * The constraint type name for primary key constraints. |
44 | */ |
45 | public static final String PRIMARY_KEY = "PRIMARY KEY"; |
46 | |
47 | /** |
48 | * The table for which this constraint is defined. |
49 | */ |
50 | protected Table table; |
51 | |
52 | Constraint(Schema schema, int id, String name, Table table) { |
53 | initSchemaObjectBase(schema, id, name, Trace.CONSTRAINT); |
54 | this.table = table; |
55 | this.setTemporary(table.isTemporary()); |
56 | } |
57 | |
58 | /** |
59 | * The constraint type name |
60 | * |
61 | * @return the name |
62 | */ |
63 | public abstract String getConstraintType(); |
64 | |
65 | /** |
66 | * Check if this row fulfils the constraint. |
67 | * This method throws an exception if not. |
68 | * |
69 | * @param session the session |
70 | * @param t the table |
71 | * @param oldRow the old row |
72 | * @param newRow the new row |
73 | */ |
74 | public abstract void checkRow(Session session, Table t, Row oldRow, Row newRow); |
75 | |
76 | /** |
77 | * Check if this constraint needs the specified index. |
78 | * |
79 | * @param index the index |
80 | * @return true if the index is used |
81 | */ |
82 | public abstract boolean usesIndex(Index index); |
83 | |
84 | /** |
85 | * This index is now the owner of the specified index. |
86 | * |
87 | * @param index the index |
88 | */ |
89 | public abstract void setIndexOwner(Index index); |
90 | |
91 | /** |
92 | * Get all referenced columns. |
93 | * |
94 | * @param table the table |
95 | * @return the set of referenced columns |
96 | */ |
97 | public abstract HashSet<Column> getReferencedColumns(Table table); |
98 | |
99 | /** |
100 | * Get the SQL statement to create this constraint. |
101 | * |
102 | * @return the SQL statement |
103 | */ |
104 | public abstract String getCreateSQLWithoutIndexes(); |
105 | |
106 | /** |
107 | * Check if this constraint needs to be checked before updating the data. |
108 | * |
109 | * @return true if it must be checked before updating |
110 | */ |
111 | public abstract boolean isBefore(); |
112 | |
113 | /** |
114 | * Check the existing data. This method is called if the constraint is added |
115 | * after data has been inserted into the table. |
116 | * |
117 | * @param session the session |
118 | */ |
119 | public abstract void checkExistingData(Session session); |
120 | |
121 | /** |
122 | * This method is called after a related table has changed |
123 | * (the table was renamed, or columns have been renamed). |
124 | */ |
125 | public abstract void rebuild(); |
126 | |
127 | /** |
128 | * Get the unique index used to enforce this constraint, or null if no index |
129 | * is used. |
130 | * |
131 | * @return the index |
132 | */ |
133 | public abstract Index getUniqueIndex(); |
134 | |
135 | @Override |
136 | public void checkRename() { |
137 | // ok |
138 | } |
139 | |
140 | @Override |
141 | public int getType() { |
142 | return DbObject.CONSTRAINT; |
143 | } |
144 | |
145 | public Table getTable() { |
146 | return table; |
147 | } |
148 | |
149 | public Table getRefTable() { |
150 | return table; |
151 | } |
152 | |
153 | @Override |
154 | public String getDropSQL() { |
155 | return null; |
156 | } |
157 | |
158 | private int getConstraintTypeOrder() { |
159 | String constraintType = getConstraintType(); |
160 | if (CHECK.equals(constraintType)) { |
161 | return 0; |
162 | } else if (PRIMARY_KEY.equals(constraintType)) { |
163 | return 1; |
164 | } else if (UNIQUE.equals(constraintType)) { |
165 | return 2; |
166 | } else if (REFERENTIAL.equals(constraintType)) { |
167 | return 3; |
168 | } else { |
169 | throw DbException.throwInternalError("type: " + constraintType); |
170 | } |
171 | } |
172 | |
173 | @Override |
174 | public int compareTo(Constraint other) { |
175 | if (this == other) { |
176 | return 0; |
177 | } |
178 | int thisType = getConstraintTypeOrder(); |
179 | int otherType = other.getConstraintTypeOrder(); |
180 | return thisType - otherType; |
181 | } |
182 | |
183 | @Override |
184 | public boolean isHidden() { |
185 | return table.isHidden(); |
186 | } |
187 | |
188 | /** |
189 | * Visit all elements in the constraint. |
190 | * |
191 | * @param visitor the visitor |
192 | * @return true if every visited expression returned true, or if there are |
193 | * no expressions |
194 | */ |
195 | public boolean isEverything(ExpressionVisitor visitor) { |
196 | return true; |
197 | } |
198 | |
199 | } |