1 | /* |
2 | |
3 | Derby - Class org.apache.derby.iapi.sql.dictionary.CatalogRowFactory |
4 | |
5 | Copyright 1997, 2004 The Apache Software Foundation or its licensors, as applicable. |
6 | |
7 | Licensed under the Apache License, Version 2.0 (the "License"); |
8 | you may not use this file except in compliance with the License. |
9 | You may obtain a copy of the License at |
10 | |
11 | http://www.apache.org/licenses/LICENSE-2.0 |
12 | |
13 | Unless required by applicable law or agreed to in writing, software |
14 | distributed under the License is distributed on an "AS IS" BASIS, |
15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
16 | See the License for the specific language governing permissions and |
17 | limitations under the License. |
18 | |
19 | */ |
20 | |
21 | package org.apache.derby.iapi.sql.dictionary; |
22 | |
23 | import org.apache.derby.iapi.reference.Property; |
24 | import org.apache.derby.iapi.util.StringUtil; |
25 | |
26 | import org.apache.derby.iapi.services.context.ContextService; |
27 | import org.apache.derby.iapi.services.monitor.Monitor; |
28 | import org.apache.derby.iapi.services.sanity.SanityManager; |
29 | import org.apache.derby.iapi.error.StandardException; |
30 | import org.apache.derby.iapi.types.DataValueFactory; |
31 | import org.apache.derby.iapi.sql.execute.ExecutionFactory; |
32 | import org.apache.derby.iapi.sql.execute.ExecIndexRow; |
33 | import org.apache.derby.iapi.sql.execute.ExecRow; |
34 | import org.apache.derby.iapi.sql.execute.ExecutionContext; |
35 | import org.apache.derby.iapi.types.DataValueFactory; |
36 | import org.apache.derby.iapi.types.RowLocation; |
37 | import org.apache.derby.iapi.store.raw.RawStoreFactory; |
38 | import org.apache.derby.iapi.services.uuid.UUIDFactory; |
39 | import org.apache.derby.catalog.UUID; |
40 | import java.util.Properties; |
41 | |
42 | /** |
43 | * Superclass of all row factories. |
44 | * |
45 | * |
46 | * @version 0.2 |
47 | * @author Rick Hillegas |
48 | * @author Manish Khettry |
49 | */ |
50 | |
51 | public abstract class CatalogRowFactory |
52 | { |
53 | /////////////////////////////////////////////////////////////////////////// |
54 | // |
55 | // STATE |
56 | // |
57 | /////////////////////////////////////////////////////////////////////////// |
58 | |
59 | |
60 | protected String[] indexNames; |
61 | protected int[][] indexColumnPositions; |
62 | protected String[][] indexColumnNames; |
63 | protected boolean[] indexUniqueness; |
64 | |
65 | protected UUID tableUUID; |
66 | protected UUID heapUUID; |
67 | protected UUID[] indexUUID; |
68 | |
69 | protected DataValueFactory dvf; |
70 | private final ExecutionFactory ef; |
71 | private UUIDFactory uuidf; |
72 | |
73 | private boolean convertIdToLower; |
74 | private int indexCount; |
75 | private int columnCount; |
76 | private String catalogName; |
77 | |
78 | /////////////////////////////////////////////////////////////////////////// |
79 | // |
80 | // CONSTRUCTORS |
81 | // |
82 | /////////////////////////////////////////////////////////////////////////// |
83 | |
84 | public CatalogRowFactory(UUIDFactory uuidf, |
85 | ExecutionFactory ef, |
86 | DataValueFactory dvf, |
87 | boolean convertIdToLower) |
88 | |
89 | { |
90 | this.uuidf = uuidf; |
91 | this.dvf = dvf; |
92 | this.ef = ef; |
93 | this.convertIdToLower = convertIdToLower; |
94 | } |
95 | |
96 | /** |
97 | * Gets a ExecutionFactory |
98 | * |
99 | * @return an execution factory |
100 | */ |
101 | public ExecutionFactory getExecutionFactory() {return ef;} |
102 | |
103 | /** |
104 | * Get the UUID factory |
105 | * |
106 | * @return the UUID factory |
107 | */ |
108 | public UUIDFactory getUUIDFactory() { return uuidf; } |
109 | |
110 | /* Override the following methods in sub-classes if they have any |
111 | * indexes. |
112 | */ |
113 | |
114 | /** |
115 | * Get the UUID of this catalog. This is the hard-coded uuid for |
116 | * this catalog that is generated for releases starting with Plato (1.3). |
117 | * Earlier releases generated their own UUIDs for system objectss on |
118 | * the fly. |
119 | * |
120 | * @return the name of this catalog |
121 | */ |
122 | public UUID getCanonicalTableUUID() { return tableUUID; } |
123 | |
124 | /** |
125 | * Get the UUID of the heap underlying this catalog. See getCanonicalTableUUID() |
126 | * for a description of canonical uuids. |
127 | * |
128 | * @return the uuid of the heap |
129 | */ |
130 | public UUID getCanonicalHeapUUID() { return heapUUID; } |
131 | |
132 | /** |
133 | * Get the UUID of the numbered index. See getCanonicalTableUUID() |
134 | * for a description of canonical uuids. |
135 | * |
136 | * @param indexNumber The (0-based) index number. |
137 | * |
138 | * @return the uuid of the heap |
139 | */ |
140 | public UUID getCanonicalIndexUUID( int indexNumber ) |
141 | { |
142 | if (SanityManager.DEBUG) |
143 | checkIndexNumber(indexNumber); |
144 | |
145 | return indexUUID[indexNumber]; |
146 | } |
147 | |
148 | /** |
149 | * Get the number of columns in the index for the specified index number. |
150 | * |
151 | * @param indexNum The (0-based) index number. |
152 | * |
153 | * @return int The number of columns in the index for the specifed index number. |
154 | */ |
155 | public int getIndexColumnCount(int indexNum) |
156 | { |
157 | if (SanityManager.DEBUG) |
158 | checkIndexNumber(indexNum); |
159 | |
160 | return indexColumnPositions[indexNum].length; |
161 | } |
162 | |
163 | /** |
164 | * Get the name for the heap conglomerate underlying this catalog. |
165 | * See getCanonicalTableUUID() for a description of canonical uuids. |
166 | * |
167 | * @return String The name for the heap conglomerate. |
168 | */ |
169 | public String getCanonicalHeapName() { return catalogName + convertIdCase( "_HEAP"); } |
170 | |
171 | /** |
172 | * Get the name for the specified index number. |
173 | * |
174 | * @param indexNum The (0-based) index number. |
175 | * |
176 | * @return String The name for the specified index number. |
177 | */ |
178 | public String getIndexName(int indexNum) |
179 | { |
180 | if (SanityManager.DEBUG) |
181 | checkIndexNumber(indexNum); |
182 | |
183 | return indexNames[indexNum]; |
184 | } |
185 | |
186 | /** |
187 | * Return whether or not the specified index is unique. |
188 | * |
189 | * @param indexNumber The (0-based) index number. |
190 | * |
191 | * @return boolean Whether or not the specified index is unique. |
192 | */ |
193 | public boolean isIndexUnique(int indexNumber) |
194 | { |
195 | if (SanityManager.DEBUG) |
196 | checkIndexNumber(indexNumber); |
197 | |
198 | return (indexUniqueness != null ? indexUniqueness[indexNumber] : true); |
199 | } |
200 | |
201 | /** |
202 | * Gets the DataValueFactory for this connection. |
203 | * |
204 | * @return the data value factory for this connection |
205 | */ |
206 | public DataValueFactory getDataValueFactory() { return dvf; } |
207 | |
208 | /** |
209 | * Generate an index name based on the index number. |
210 | * |
211 | * @param indexNumber Number of index |
212 | * |
213 | * @return the following index name: CatalogName + "_INDEX" + (indexNumber+1) |
214 | */ |
215 | public String generateIndexName( int indexNumber ) |
216 | { |
217 | indexNumber++; |
218 | return catalogName + convertIdCase( "_INDEX") + indexNumber; |
219 | } |
220 | |
221 | /** get the number of indexes on this catalog */ |
222 | public int getNumIndexes() { return indexCount; } |
223 | |
224 | /** get the name of the catalog */ |
225 | public String getCatalogName() { return catalogName; }; |
226 | |
227 | /** |
228 | * Initialize info, including array of index names and array of |
229 | * index column counts. Called at constructor time. |
230 | * |
231 | * @param columnCount number of columns in the base table. |
232 | * @param catalogName name of the catalog (the case might have to be converted). |
233 | * @param indexColumnPositions 2 dim array of ints specifying the base |
234 | * column positions for each index. |
235 | * @param indexColumnNames 2 dim array of Strings specifying the name |
236 | * of the base column for each index. |
237 | * @param indexUniqueness Uniqueness of the indices |
238 | * @param uuidStrings Array of stringified UUIDs for table and its conglomerates |
239 | * |
240 | */ |
241 | public void initInfo(int columnCount, |
242 | String catalogName, |
243 | int[][] indexColumnPositions, |
244 | String[][] indexColumnNames, |
245 | boolean[] indexUniqueness, |
246 | String[] uuidStrings) |
247 | |
248 | { |
249 | indexCount = (indexColumnPositions != null) ? |
250 | indexColumnPositions.length : 0; |
251 | |
252 | this.catalogName = convertIdCase(catalogName); |
253 | this.columnCount = columnCount; |
254 | |
255 | UUIDFactory uf = getUUIDFactory(); |
256 | this.tableUUID = uf.recreateUUID(uuidStrings[0] ); |
257 | this.heapUUID = uf.recreateUUID( uuidStrings[1] ); |
258 | |
259 | if (indexCount > 0) |
260 | { |
261 | indexNames = new String[indexCount]; |
262 | indexUUID = new UUID[indexCount]; |
263 | for (int ictr = 0; ictr < indexCount; ictr++) |
264 | { |
265 | indexNames[ictr] = generateIndexName(ictr); |
266 | indexUUID[ictr] = uf.recreateUUID(uuidStrings[ictr + 2 ]); |
267 | } |
268 | this.indexColumnPositions = indexColumnPositions; |
269 | this.indexColumnNames = indexColumnNames; |
270 | this.indexUniqueness = indexUniqueness; |
271 | |
272 | |
273 | } |
274 | } |
275 | |
276 | /** |
277 | * Get the Properties associated with creating the heap. |
278 | * |
279 | * @return The Properties associated with creating the heap. |
280 | */ |
281 | public Properties getCreateHeapProperties() |
282 | { |
283 | Properties properties = new Properties(); |
284 | // default properties for system tables: |
285 | properties.put(Property.PAGE_SIZE_PARAMETER,"1024"); |
286 | properties.put(RawStoreFactory.PAGE_RESERVED_SPACE_PARAMETER,"0"); |
287 | properties.put(RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER,"1"); |
288 | return properties; |
289 | } |
290 | |
291 | /** |
292 | * Get the Properties associated with creating the specified index. |
293 | * |
294 | * @param indexNumber The specified index number. |
295 | * |
296 | * @return The Properties associated with creating the specified index. |
297 | */ |
298 | public Properties getCreateIndexProperties(int indexNumber) |
299 | { |
300 | Properties properties = new Properties(); |
301 | // default properties for system indexes: |
302 | properties.put(Property.PAGE_SIZE_PARAMETER,"1024"); |
303 | return properties; |
304 | } |
305 | |
306 | /** |
307 | * Get the index number for the primary key index on this catalog. |
308 | * |
309 | * @return a 0-based number |
310 | * |
311 | */ |
312 | public int getPrimaryKeyIndexNumber() |
313 | { |
314 | if (SanityManager.DEBUG) |
315 | SanityManager.NOTREACHED(); |
316 | return 0; |
317 | } |
318 | |
319 | /** |
320 | * Get the number of columns in the heap. |
321 | * |
322 | * @return The number of columns in the heap. |
323 | */ |
324 | public final int getHeapColumnCount() |
325 | { |
326 | return columnCount; |
327 | } |
328 | |
329 | protected String convertIdCase( String id) |
330 | { |
331 | if( convertIdToLower) |
332 | return StringUtil.SQLToLowerCase(id); |
333 | else |
334 | return id; |
335 | } |
336 | |
337 | |
338 | /** |
339 | * Return an empty row for this conglomerate. |
340 | */ |
341 | public ExecRow makeEmptyRow() throws StandardException |
342 | { |
343 | return this.makeRow(null, null); |
344 | } |
345 | |
346 | /** |
347 | * most subclasses should provide this method. One or two oddball cases in |
348 | * Replication and SysSTATEMENTSRowFactory don't. For those we call makeRow |
349 | * with the additional arguments. |
350 | */ |
351 | public ExecRow makeRow(TupleDescriptor td, TupleDescriptor parent) throws StandardException |
352 | { |
353 | if (SanityManager.DEBUG) { SanityManager.THROWASSERT( "Should not get here." ); } |
354 | return null; |
355 | } |
356 | |
357 | // abstract classes that should be implemented by subclasses. |
358 | |
359 | /** builds a tuple descriptor from a row */ |
360 | public abstract TupleDescriptor |
361 | buildDescriptor(ExecRow row, |
362 | TupleDescriptor parentTuple, |
363 | DataDictionary dataDictionary) |
364 | throws StandardException; |
365 | |
366 | /** builds a column list for the catalog */ |
367 | public abstract SystemColumn[] buildColumnList(); |
368 | |
369 | /** |
370 | * builds an empty row given for a given index number. |
371 | */ |
372 | public abstract ExecIndexRow buildEmptyIndexRow(int indexNumber, |
373 | RowLocation rowLocation) |
374 | throws StandardException; |
375 | |
376 | /** Return the column positions for a given index number */ |
377 | public int[] getIndexColumnPositions(int indexNumber) |
378 | { |
379 | if (SanityManager.DEBUG) |
380 | checkIndexNumber(indexNumber); |
381 | |
382 | return indexColumnPositions[indexNumber]; |
383 | } |
384 | |
385 | /** Return the names of columns for a given index number */ |
386 | public String[] getIndexColumnNames(int indexNumber) |
387 | { |
388 | if (SanityManager.DEBUG) |
389 | checkIndexNumber(indexNumber); |
390 | |
391 | if (!convertIdToLower) |
392 | return indexColumnNames[indexNumber]; |
393 | |
394 | String[] s = new String[indexColumnNames[indexNumber].length]; |
395 | for (int i = 0; i < s.length; i++) |
396 | s[i] = StringUtil.SQLToLowerCase(indexColumnNames[indexNumber][i]); |
397 | return s; |
398 | } |
399 | |
400 | protected void checkIndexNumber(int indexNumber) |
401 | { |
402 | if (SanityManager.DEBUG) |
403 | { |
404 | if (!(indexNumber < indexCount)) |
405 | { |
406 | SanityManager.THROWASSERT("indexNumber (" + |
407 | indexNumber + ") expected to be < " + indexCount); |
408 | } |
409 | } |
410 | } |
411 | } |