1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.healthmarketscience.jackcess.impl;
18
19 import java.util.ArrayList;
20 import java.util.List;
21 import java.util.Set;
22
23 import com.healthmarketscience.jackcess.ColumnBuilder;
24 import com.healthmarketscience.jackcess.DataType;
25 import com.healthmarketscience.jackcess.IndexBuilder;
26
27
28
29
30
31
32
33 public abstract class TableMutator extends DBMutator
34 {
35 private ColumnOffsets _colOffsets;
36
37 protected TableMutator(DatabaseImpl database) {
38 super(database);
39 }
40
41 public void setColumnOffsets(
42 int fixedOffset, int varOffset, int longVarOffset) {
43 if(_colOffsets == null) {
44 _colOffsets = new ColumnOffsets();
45 }
46 _colOffsets.set(fixedOffset, varOffset, longVarOffset);
47 }
48
49 public ColumnOffsets getColumnOffsets() {
50 return _colOffsets;
51 }
52
53 public IndexImpl.ForeignKeyReference getForeignKey(IndexBuilder idx) {
54 return null;
55 }
56
57 protected void validateColumn(Set<String> colNames, ColumnBuilder column) {
58
59
60 if(column.getType() == DataType.COMPLEX_TYPE) {
61 throw new UnsupportedOperationException(withErrorContext(
62 "Complex column creation is not yet implemented"));
63 }
64
65 column.validate(getFormat());
66 if(!colNames.add(DatabaseImpl.toLookupName(column.getName()))) {
67 throw new IllegalArgumentException(withErrorContext(
68 "duplicate column name: " + column.getName()));
69 }
70
71 setColumnSortOrder(column);
72 }
73
74 protected void validateIndex(Set<String> colNames, Set<String> idxNames,
75 boolean[] foundPk, IndexBuilder index) {
76
77 index.validate(colNames, getFormat());
78 if(!idxNames.add(DatabaseImpl.toLookupName(index.getName()))) {
79 throw new IllegalArgumentException(withErrorContext(
80 "duplicate index name: " + index.getName()));
81 }
82 if(index.isPrimaryKey()) {
83 if(foundPk[0]) {
84 throw new IllegalArgumentException(withErrorContext(
85 "found second primary key index: " + index.getName()));
86 }
87 foundPk[0] = true;
88 } else if(index.getType() == IndexImpl.FOREIGN_KEY_INDEX_TYPE) {
89 if(getForeignKey(index) == null) {
90 throw new IllegalArgumentException(withErrorContext(
91 "missing foreign key info for " + index.getName()));
92 }
93 }
94 }
95
96 protected void validateAutoNumberColumn(Set<DataType> autoTypes,
97 ColumnBuilder column)
98 {
99 if(!column.getType().isMultipleAutoNumberAllowed() &&
100 !autoTypes.add(column.getType())) {
101 throw new IllegalArgumentException(withErrorContext(
102 "Can have at most one AutoNumber column of type " + column.getType() +
103 " per table"));
104 }
105 }
106
107 private void setColumnSortOrder(ColumnBuilder column) {
108
109 if(column.getType().isTextual() && (column.getTextSortOrder() == null)) {
110 column.setTextSortOrder(getDbSortOrder());
111 }
112 }
113
114 abstract String getTableName();
115
116 public abstract int getTdefPageNumber();
117
118 abstract short getColumnNumber(String colName);
119
120 public abstract ColumnState getColumnState(ColumnBuilder col);
121
122 public abstract IndexDataState getIndexDataState(IndexBuilder idx);
123
124 protected abstract String withErrorContext(String msg);
125
126
127
128
129
130 static final class ColumnOffsets
131 {
132 private short _fixedOffset;
133 private short _varOffset;
134 private short _longVarOffset;
135
136 public void set(int fixedOffset, int varOffset, int longVarOffset) {
137 _fixedOffset = (short)fixedOffset;
138 _varOffset = (short)varOffset;
139 _longVarOffset = (short)longVarOffset;
140 }
141
142 public short getNextVariableOffset(ColumnBuilder col) {
143 if(!col.getType().isLongValue()) {
144 return _varOffset++;
145 }
146 return _longVarOffset++;
147 }
148
149 public short getNextFixedOffset(ColumnBuilder col) {
150 short offset = _fixedOffset;
151 _fixedOffset += col.getType().getFixedSize(col.getLength());
152 return offset;
153 }
154 }
155
156
157
158
159
160 static final class ColumnState
161 {
162 private byte _umapOwnedRowNumber;
163 private byte _umapFreeRowNumber;
164
165 private int _umapPageNumber;
166
167 public byte getUmapOwnedRowNumber() {
168 return _umapOwnedRowNumber;
169 }
170
171 public void setUmapOwnedRowNumber(byte newUmapOwnedRowNumber) {
172 _umapOwnedRowNumber = newUmapOwnedRowNumber;
173 }
174
175 public byte getUmapFreeRowNumber() {
176 return _umapFreeRowNumber;
177 }
178
179 public void setUmapFreeRowNumber(byte newUmapFreeRowNumber) {
180 _umapFreeRowNumber = newUmapFreeRowNumber;
181 }
182
183 public int getUmapPageNumber() {
184 return _umapPageNumber;
185 }
186
187 public void setUmapPageNumber(int newUmapPageNumber) {
188 _umapPageNumber = newUmapPageNumber;
189 }
190 }
191
192
193
194
195
196 static final class IndexDataState
197 {
198 private final List<IndexBuilder> _indexes = new ArrayList<IndexBuilder>();
199 private int _indexDataNumber;
200 private byte _umapRowNumber;
201 private int _umapPageNumber;
202 private int _rootPageNumber;
203
204 public IndexBuilder getFirstIndex() {
205
206
207 return _indexes.get(0);
208 }
209
210 public List<IndexBuilder> getIndexes() {
211 return _indexes;
212 }
213
214 public void addIndex(IndexBuilder idx) {
215 _indexes.add(idx);
216 }
217
218 public int getIndexDataNumber() {
219 return _indexDataNumber;
220 }
221
222 public void setIndexDataNumber(int newIndexDataNumber) {
223 _indexDataNumber = newIndexDataNumber;
224 }
225
226 public byte getUmapRowNumber() {
227 return _umapRowNumber;
228 }
229
230 public void setUmapRowNumber(byte newUmapRowNumber) {
231 _umapRowNumber = newUmapRowNumber;
232 }
233
234 public int getUmapPageNumber() {
235 return _umapPageNumber;
236 }
237
238 public void setUmapPageNumber(int newUmapPageNumber) {
239 _umapPageNumber = newUmapPageNumber;
240 }
241
242 public int getRootPageNumber() {
243 return _rootPageNumber;
244 }
245
246 public void setRootPageNumber(int newRootPageNumber) {
247 _rootPageNumber = newRootPageNumber;
248 }
249 }
250 }