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 column.validate(getFormat());
60 if(!colNames.add(DatabaseImpl.toLookupName(column.getName()))) {
61 throw new IllegalArgumentException(withErrorContext(
62 "duplicate column name: " + column.getName()));
63 }
64
65 setColumnSortOrder(column);
66 }
67
68 protected void validateIndex(Set<String> colNames, Set<String> idxNames,
69 boolean[] foundPk, IndexBuilder index) {
70
71 index.validate(colNames, getFormat());
72 if(!idxNames.add(DatabaseImpl.toLookupName(index.getName()))) {
73 throw new IllegalArgumentException(withErrorContext(
74 "duplicate index name: " + index.getName()));
75 }
76 if(index.isPrimaryKey()) {
77 if(foundPk[0]) {
78 throw new IllegalArgumentException(withErrorContext(
79 "found second primary key index: " + index.getName()));
80 }
81 foundPk[0] = true;
82 } else if(index.getType() == IndexImpl.FOREIGN_KEY_INDEX_TYPE) {
83 if(getForeignKey(index) == null) {
84 throw new IllegalArgumentException(withErrorContext(
85 "missing foreign key info for " + index.getName()));
86 }
87 }
88 }
89
90 protected void validateAutoNumberColumn(Set<DataType> autoTypes,
91 ColumnBuilder column)
92 {
93 if(!column.getType().isMultipleAutoNumberAllowed() &&
94 !autoTypes.add(column.getType())) {
95 throw new IllegalArgumentException(withErrorContext(
96 "Can have at most one AutoNumber column of type " + column.getType() +
97 " per table"));
98 }
99 }
100
101 private void setColumnSortOrder(ColumnBuilder column) {
102
103 if(column.getType().isTextual() && (column.getTextSortOrder() == null)) {
104 column.setTextSortOrder(getDbSortOrder());
105 }
106 }
107
108 abstract String getTableName();
109
110 public abstract int getTdefPageNumber();
111
112 abstract short getColumnNumber(String colName);
113
114
115
116
117
118 abstract boolean isComplexColumn(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.isVariableLength()) {
144 return _varOffset;
145 }
146 if(!col.getType().isLongValue()) {
147 return _varOffset++;
148 }
149 return _longVarOffset++;
150 }
151
152 public short getNextFixedOffset(ColumnBuilder col) {
153 if(col.storeInNullMask()) {
154
155 return 0;
156 }
157 short offset = _fixedOffset;
158 _fixedOffset += col.getFixedDataSize();
159 return offset;
160 }
161 }
162
163
164
165
166
167 static final class ColumnState
168 {
169 private byte _umapOwnedRowNumber;
170 private byte _umapFreeRowNumber;
171
172 private int _umapPageNumber;
173 private int _complexId;
174 private byte _extraFlags;
175
176 public int getComplexId() {
177 return _complexId;
178 }
179
180 public void setComplexId(int newComplexId) {
181 _complexId = newComplexId;
182 }
183
184 public byte getExtraFlags() {
185 return _extraFlags;
186 }
187
188 public void setExtraFlags(byte newExtraFlags) {
189 _extraFlags = newExtraFlags;
190 }
191
192 public byte getUmapOwnedRowNumber() {
193 return _umapOwnedRowNumber;
194 }
195
196 public void setUmapOwnedRowNumber(byte newUmapOwnedRowNumber) {
197 _umapOwnedRowNumber = newUmapOwnedRowNumber;
198 }
199
200 public byte getUmapFreeRowNumber() {
201 return _umapFreeRowNumber;
202 }
203
204 public void setUmapFreeRowNumber(byte newUmapFreeRowNumber) {
205 _umapFreeRowNumber = newUmapFreeRowNumber;
206 }
207
208 public int getUmapPageNumber() {
209 return _umapPageNumber;
210 }
211
212 public void setUmapPageNumber(int newUmapPageNumber) {
213 _umapPageNumber = newUmapPageNumber;
214 }
215 }
216
217
218
219
220
221 static final class IndexDataState
222 {
223 private final List<IndexBuilder> _indexes = new ArrayList<>();
224 private int _indexDataNumber;
225 private byte _umapRowNumber;
226 private int _umapPageNumber;
227 private int _rootPageNumber;
228
229 public IndexBuilder getFirstIndex() {
230
231
232 return _indexes.get(0);
233 }
234
235 public List<IndexBuilder> getIndexes() {
236 return _indexes;
237 }
238
239 public void addIndex(IndexBuilder idx) {
240 _indexes.add(idx);
241 }
242
243 public int getIndexDataNumber() {
244 return _indexDataNumber;
245 }
246
247 public void setIndexDataNumber(int newIndexDataNumber) {
248 _indexDataNumber = newIndexDataNumber;
249 }
250
251 public byte getUmapRowNumber() {
252 return _umapRowNumber;
253 }
254
255 public void setUmapRowNumber(byte newUmapRowNumber) {
256 _umapRowNumber = newUmapRowNumber;
257 }
258
259 public int getUmapPageNumber() {
260 return _umapPageNumber;
261 }
262
263 public void setUmapPageNumber(int newUmapPageNumber) {
264 _umapPageNumber = newUmapPageNumber;
265 }
266
267 public int getRootPageNumber() {
268 return _rootPageNumber;
269 }
270
271 public void setRootPageNumber(int newRootPageNumber) {
272 _rootPageNumber = newRootPageNumber;
273 }
274 }
275 }