001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.catalog.SYSCOLUMNSRowFactory
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.impl.sql.catalog;
023:
024: import org.apache.derby.iapi.reference.Property;
025:
026: import org.apache.derby.iapi.types.DataTypeDescriptor;
027: import org.apache.derby.iapi.types.TypeId;
028: import org.apache.derby.iapi.types.DataValueDescriptor;
029:
030: import org.apache.derby.iapi.store.raw.RawStoreFactory;
031:
032: import org.apache.derby.iapi.types.DataValueFactory;
033: import org.apache.derby.iapi.sql.dictionary.SystemColumn;
034: import org.apache.derby.catalog.TypeDescriptor;
035: import org.apache.derby.catalog.types.BaseTypeIdImpl;
036:
037: import org.apache.derby.iapi.types.DataValueDescriptor;
038:
039: import org.apache.derby.iapi.types.TypeId;
040: import org.apache.derby.iapi.types.DataTypeDescriptor;
041: import org.apache.derby.iapi.types.DataValueFactory;
042: import org.apache.derby.iapi.types.RowLocation;
043:
044: import org.apache.derby.iapi.sql.dictionary.CatalogRowFactory;
045: import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor;
046: import org.apache.derby.iapi.sql.dictionary.DataDescriptorGenerator;
047: import org.apache.derby.iapi.sql.dictionary.DataDictionary;
048: import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
049: import org.apache.derby.iapi.sql.dictionary.TupleDescriptor;
050: import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
051: import org.apache.derby.iapi.sql.dictionary.UniqueTupleDescriptor;
052:
053: import org.apache.derby.iapi.sql.execute.ExecutionContext;
054: import org.apache.derby.iapi.sql.execute.ExecutionFactory;
055: import org.apache.derby.iapi.sql.execute.ExecIndexRow;
056: import org.apache.derby.iapi.sql.execute.ExecRow;
057:
058: import org.apache.derby.iapi.error.StandardException;
059:
060: import org.apache.derby.iapi.services.sanity.SanityManager;
061:
062: import org.apache.derby.iapi.services.monitor.Monitor;
063: import org.apache.derby.catalog.types.TypeDescriptorImpl;
064: import org.apache.derby.catalog.DefaultInfo;
065: import org.apache.derby.iapi.services.uuid.UUIDFactory;
066: import org.apache.derby.catalog.UUID;
067:
068: import org.apache.derby.impl.sql.compile.ColumnDefinitionNode;
069:
070: import org.apache.derby.catalog.types.DefaultInfoImpl;
071:
072: import org.apache.derby.iapi.types.*;
073:
074: import java.io.Serializable;
075:
076: import java.util.Properties;
077:
078: /**
079: * Factory for creating a SYSCOLUMNS row.
080: *
081: *
082: * @version 0.1
083: * @author Rick Hillegas (extracted from DataDictionaryImpl).
084: */
085:
086: public class SYSCOLUMNSRowFactory extends CatalogRowFactory {
087: static final String TABLENAME_STRING = "SYSCOLUMNS";
088:
089: /**
090: * Old name for REFERENCEID, used by upgrade
091: */
092: public static final String OLD_REFERENCEID_NAME = "TABLEID";
093:
094: protected static final int SYSCOLUMNS_COLUMN_COUNT = 9;
095: /* Column #s for syscolumns (1 based) */
096:
097: //TABLEID is an obsolete name, it is better to use
098: //REFERENCEID, but to make life easier you can use either
099: protected static final int SYSCOLUMNS_TABLEID = 1;
100: protected static final int SYSCOLUMNS_REFERENCEID = 1;
101: protected static final int SYSCOLUMNS_COLUMNNAME = 2;
102: protected static final int SYSCOLUMNS_COLUMNNUMBER = 3;
103: protected static final int SYSCOLUMNS_COLUMNDATATYPE = 4;
104: protected static final int SYSCOLUMNS_COLUMNDEFAULT = 5;
105: protected static final int SYSCOLUMNS_COLUMNDEFAULTID = 6;
106: protected static final int SYSCOLUMNS_AUTOINCREMENTVALUE = 7;
107: protected static final int SYSCOLUMNS_AUTOINCREMENTSTART = 8;
108: protected static final int SYSCOLUMNS_AUTOINCREMENTINC = 9;
109:
110: //private static final String SYSCOLUMNS_INDEX1_NAME = "SYSCOLUMNS_INDEX1";
111: protected static final int SYSCOLUMNS_INDEX1_ID = 0;
112:
113: //private static final String SYSCOLUMNS_INDEX2_NAME = "SYSCOLUMNS_INDEX2";
114: protected static final int SYSCOLUMNS_INDEX2_ID = 1;
115:
116: protected static final String REFERENCEDID_STRING = "REFERENCEID";
117: protected static final String COLUMNNAME_STRING = "COLUMNNAME";
118: protected static final String COLUMNDEFAULTID_STRING = "COLUMNDEFAULTID";
119:
120: private static final boolean[] uniqueness = { true, false };
121:
122: private static final String[] uuids = {
123: "8000001e-00d0-fd77-3ed8-000a0a0b1900" // catalog UUID
124: , "80000029-00d0-fd77-3ed8-000a0a0b1900" // heap UUID
125: , "80000020-00d0-fd77-3ed8-000a0a0b1900" // SYSCOLUMNS_INDEX1 UUID
126: , "6839c016-00d9-2829-dfcd-000a0a411400" // SYSCOLUMNS_INDEX2 UUID
127: };
128:
129: private static final int[][] indexColumnPositions = {
130: { SYSCOLUMNS_REFERENCEID, SYSCOLUMNS_COLUMNNAME },
131: { SYSCOLUMNS_COLUMNDEFAULTID } };
132:
133: /////////////////////////////////////////////////////////////////////////////
134: //
135: // STATE
136: //
137: /////////////////////////////////////////////////////////////////////////////
138:
139: private SystemColumn[] columnList;
140:
141: /////////////////////////////////////////////////////////////////////////////
142: //
143: // CONSTRUCTORS
144: //
145: /////////////////////////////////////////////////////////////////////////////
146:
147: public SYSCOLUMNSRowFactory(UUIDFactory uuidf, ExecutionFactory ef,
148: DataValueFactory dvf, boolean convertIdToLower) {
149: this (uuidf, ef, dvf, convertIdToLower, TABLENAME_STRING);
150: }
151:
152: public SYSCOLUMNSRowFactory(UUIDFactory uuidf, ExecutionFactory ef,
153: DataValueFactory dvf, boolean convertIdToLower,
154: String myName) {
155: super (uuidf, ef, dvf, convertIdToLower);
156: initInfo(SYSCOLUMNS_COLUMN_COUNT, myName, indexColumnPositions,
157: uniqueness, uuids);
158: }
159:
160: /////////////////////////////////////////////////////////////////////////////
161: //
162: // METHODS
163: //
164: /////////////////////////////////////////////////////////////////////////////
165:
166: /**
167: * Make a SYSCOLUMNS row
168: *
169: * @return Row suitable for inserting into SYSCOLUMNS.
170: *
171: * @exception StandardException thrown on failure
172: */
173:
174: public ExecRow makeRow(TupleDescriptor td, TupleDescriptor parent)
175: throws StandardException {
176: ExecRow row;
177: DataValueDescriptor col;
178:
179: String colName = null;
180: String defaultID = null;
181: String tabID = null;
182: Integer colID = null;
183: TypeDescriptorImpl typeDesc = null;
184: Object defaultSerializable = null;
185: long autoincStart = 0;
186: long autoincInc = 0;
187: //The SYSCOLUMNS table's autoinc related columns change with different
188: //values depending on what happened to the autoinc column, ie is the
189: //user adding an autoincrement column, or is user changing the existing
190: //autoincrement column to change it's increment value or to change it's
191: //start value? Following variable is used to keep track of what happened
192: //to the autoincrement column.
193: long autoinc_create_or_modify_Start_Increment = -1;
194:
195: if (td != null) {
196: ColumnDescriptor column = (ColumnDescriptor) td;
197:
198: /* Lots of info in the column's type descriptor */
199: typeDesc = column.getType().getCatalogType();
200:
201: tabID = column.getReferencingUUID().toString();
202: colName = column.getColumnName();
203: colID = new Integer(column.getPosition());
204: autoincStart = column.getAutoincStart();
205: autoincInc = column.getAutoincInc();
206: autoinc_create_or_modify_Start_Increment = column
207: .getAutoinc_create_or_modify_Start_Increment();
208: if (column.getDefaultInfo() != null) {
209: defaultSerializable = column.getDefaultInfo();
210: } else {
211: defaultSerializable = column.getDefaultValue();
212: }
213: if (column.getDefaultUUID() != null) {
214: defaultID = column.getDefaultUUID().toString();
215: }
216: }
217:
218: /* Insert info into syscolumns */
219:
220: /* RESOLVE - It would be nice to require less knowledge about syscolumns
221: * and have this be more table driven.
222: * RESOLVE - We'd like to store the DataTypeDescriptor in a column.
223: */
224:
225: /* Build the row to insert */
226: row = getExecutionFactory()
227: .getValueRow(SYSCOLUMNS_COLUMN_COUNT);
228:
229: /* 1st column is REFERENCEID (UUID - char(36)) */
230: row.setColumn(SYSCOLUMNS_REFERENCEID, dvf
231: .getCharDataValue(tabID));
232:
233: /* 2nd column is COLUMNNAME (varchar(128)) */
234: row.setColumn(SYSCOLUMNS_COLUMNNAME, dvf
235: .getVarcharDataValue(colName));
236:
237: /* 3rd column is COLUMNNUMBER (int) */
238: row.setColumn(SYSCOLUMNS_COLUMNNUMBER, dvf.getDataValue(colID));
239:
240: /* 4th column is COLUMNDATATYPE */
241: row.setColumn(SYSCOLUMNS_COLUMNDATATYPE, dvf
242: .getDataValue(typeDesc));
243:
244: /* 5th column is COLUMNDEFAULT */
245: row.setColumn(SYSCOLUMNS_COLUMNDEFAULT, dvf
246: .getDataValue(defaultSerializable));
247:
248: /* 6th column is DEFAULTID (UUID - char(36)) */
249: row.setColumn(SYSCOLUMNS_COLUMNDEFAULTID, dvf
250: .getCharDataValue(defaultID));
251:
252: if (autoinc_create_or_modify_Start_Increment == ColumnDefinitionNode.CREATE_AUTOINCREMENT
253: || autoinc_create_or_modify_Start_Increment == ColumnDefinitionNode.MODIFY_AUTOINCREMENT_INC_VALUE) {//user is adding an autoinc column or is changing the increment value of autoinc column
254: row.setColumn(SYSCOLUMNS_AUTOINCREMENTVALUE,
255: new SQLLongint(autoincStart));
256: row.setColumn(SYSCOLUMNS_AUTOINCREMENTSTART,
257: new SQLLongint(autoincStart));
258: row.setColumn(SYSCOLUMNS_AUTOINCREMENTINC, new SQLLongint(
259: autoincInc));
260: } else if (autoinc_create_or_modify_Start_Increment == ColumnDefinitionNode.MODIFY_AUTOINCREMENT_RESTART_VALUE) {//user asked for restart with a new value, so don't change increment by and original start
261: //with values in the SYSCOLUMNS table. Just record the RESTART WITH value as the
262: //next value to be generated in the SYSCOLUMNS table
263: ColumnDescriptor column = (ColumnDescriptor) td;
264: row.setColumn(SYSCOLUMNS_AUTOINCREMENTVALUE,
265: new SQLLongint(autoincStart));
266: row.setColumn(SYSCOLUMNS_AUTOINCREMENTSTART,
267: new SQLLongint(autoincStart));
268: row.setColumn(SYSCOLUMNS_AUTOINCREMENTINC, new SQLLongint(
269: column.getTableDescriptor().getColumnDescriptor(
270: colName).getAutoincInc()));
271: } else {
272: row.setColumn(SYSCOLUMNS_AUTOINCREMENTVALUE,
273: new SQLLongint());
274: row.setColumn(SYSCOLUMNS_AUTOINCREMENTSTART,
275: new SQLLongint());
276: row
277: .setColumn(SYSCOLUMNS_AUTOINCREMENTINC,
278: new SQLLongint());
279: }
280: return row;
281: }
282:
283: /**
284: * Get the Properties associated with creating the heap.
285: *
286: * @return The Properties associated with creating the heap.
287: */
288: public Properties getCreateHeapProperties() {
289: Properties properties = new Properties();
290: // keep page size at 4K since its a big table
291: properties.put(Property.PAGE_SIZE_PARAMETER, "4096");
292: // default properties for system tables:
293: properties.put(RawStoreFactory.PAGE_RESERVED_SPACE_PARAMETER,
294: "0");
295: properties.put(RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER,
296: "1");
297: return properties;
298: }
299:
300: /**
301: * Get the Properties associated with creating the specified index.
302: *
303: * @param indexNumber The specified index number.
304: *
305: * @return The Properties associated with creating the specified index.
306: */
307: public Properties getCreateIndexProperties(int indexNumber) {
308: Properties properties = new Properties();
309: // keep page size for all indexes at 4K since its a big table
310: properties.put(Property.PAGE_SIZE_PARAMETER, "4096");
311: return properties;
312: }
313:
314: ///////////////////////////////////////////////////////////////////////////
315: //
316: // ABSTRACT METHODS TO BE IMPLEMENTED BY CHILDREN OF CatalogRowFactory
317: //
318: ///////////////////////////////////////////////////////////////////////////
319:
320: /**
321: * Make a ColumnDescriptor out of a SYSCOLUMNS row
322: *
323: * @param row a SYSCOLUMNS row
324: * @param parentTupleDescriptor The UniqueTupleDescriptor for the object that is tied
325: * to this column
326: * @param dd dataDictionary
327: *
328: * @return a column descriptor equivalent to a SYSCOLUMNS row
329: *
330: * @exception StandardException thrown on failure
331: */
332: public TupleDescriptor buildDescriptor(ExecRow row,
333: TupleDescriptor parentTupleDescriptor, DataDictionary dd)
334: throws StandardException {
335: if (SanityManager.DEBUG) {
336: SanityManager.ASSERT(
337: row.nColumns() == SYSCOLUMNS_COLUMN_COUNT,
338: "Wrong number of columns for a SYSCOLUMNS row");
339: }
340:
341: int columnNumber;
342: String columnName;
343: String defaultID;
344: DefaultInfoImpl defaultInfo = null;
345: ColumnDescriptor colDesc;
346: BaseTypeIdImpl typeId;
347: TypeId wrapperTypeId;
348: DataValueDescriptor defaultValue = null;
349: UUID defaultUUID = null;
350: UUID uuid = null;
351: UUIDFactory uuidFactory = getUUIDFactory();
352: long autoincStart, autoincInc;
353:
354: DataDescriptorGenerator ddg = dd.getDataDescriptorGenerator();
355:
356: /*
357: ** We're going to be getting the UUID for this sucka
358: ** so make sure it is a UniqueTupleDescriptor.
359: */
360: if (parentTupleDescriptor != null) {
361: if (SanityManager.DEBUG) {
362: if (!(parentTupleDescriptor instanceof UniqueTupleDescriptor)) {
363: SanityManager.THROWASSERT(parentTupleDescriptor
364: .getClass().getName()
365: + " not instanceof UniqueTupleDescriptor");
366: }
367: }
368: uuid = ((UniqueTupleDescriptor) parentTupleDescriptor)
369: .getUUID();
370: } else {
371: /* 1st column is REFERENCEID (char(36)) */
372: uuid = uuidFactory.recreateUUID(row.getColumn(
373: SYSCOLUMNS_REFERENCEID).getString());
374: }
375:
376: /* NOTE: We get columns 5 and 6 next in order to work around
377: * a 1.3.0 HotSpot bug. (#4361550)
378: */
379:
380: // 5th column is COLUMNDEFAULT (serialiazable)
381: Object object = row.getColumn(SYSCOLUMNS_COLUMNDEFAULT)
382: .getObject();
383: if (object instanceof DataValueDescriptor) {
384: defaultValue = (DataValueDescriptor) object;
385: } else if (object instanceof DefaultInfoImpl) {
386: defaultInfo = (DefaultInfoImpl) object;
387: defaultValue = defaultInfo.getDefaultValue();
388: }
389:
390: /* 6th column is DEFAULTID (char(36)) */
391: defaultID = row.getColumn(SYSCOLUMNS_COLUMNDEFAULTID)
392: .getString();
393:
394: if (defaultID != null) {
395: defaultUUID = uuidFactory.recreateUUID(defaultID);
396: }
397:
398: /* 2nd column is COLUMNNAME (varchar(128)) */
399: columnName = row.getColumn(SYSCOLUMNS_COLUMNNAME).getString();
400:
401: /* 3rd column is COLUMNNUMBER (int) */
402: columnNumber = row.getColumn(SYSCOLUMNS_COLUMNNUMBER).getInt();
403:
404: /* 4th column is COLUMNDATATYPE */
405:
406: /*
407: ** What is stored in the column is a TypeDescriptorImpl, which
408: ** points to a BaseTypeIdImpl. These are simple types that are
409: ** intended to be movable to the client, so they don't have
410: ** the entire implementation. We need to wrap them in DataTypeServices
411: ** and TypeId objects that contain the full implementations for
412: ** language processing.
413: */
414: TypeDescriptorImpl typeDescriptor = (TypeDescriptorImpl) row
415: .getColumn(SYSCOLUMNS_COLUMNDATATYPE).getObject();
416: typeId = typeDescriptor.getTypeId();
417:
418: /*
419: ** The BaseTypeIdImpl tells what type of TypeId it is supposed to
420: ** be wrapped in.
421: */
422: wrapperTypeId = (TypeId) Monitor
423: .newInstanceFromIdentifier(typeId.wrapperTypeFormatId());
424: /* Wrap the BaseTypeIdImpl in a full type id */
425: wrapperTypeId.setNestedTypeId(typeId);
426:
427: /* Wrap the TypeDescriptorImpl in a full DataTypeDescriptor */
428: DataTypeDescriptor dataTypeServices = new DataTypeDescriptor(
429: typeDescriptor, wrapperTypeId);
430:
431: /* 7th column is AUTOINCREMENTVALUE, not cached in descriptor (long) */
432:
433: /* 8th column is AUTOINCREMENTSTART (long) */
434: autoincStart = row.getColumn(SYSCOLUMNS_AUTOINCREMENTSTART)
435: .getLong();
436:
437: /* 9th column is AUTOINCREMENTINC (long) */
438: autoincInc = row.getColumn(SYSCOLUMNS_AUTOINCREMENTINC)
439: .getLong();
440:
441: DataValueDescriptor col = row
442: .getColumn(SYSCOLUMNS_AUTOINCREMENTSTART);
443: autoincStart = col.getLong();
444:
445: col = row.getColumn(SYSCOLUMNS_AUTOINCREMENTINC);
446: autoincInc = col.getLong();
447:
448: colDesc = new ColumnDescriptor(columnName, columnNumber,
449: dataTypeServices, defaultValue, defaultInfo, uuid,
450: defaultUUID, autoincStart, autoincInc);
451: return colDesc;
452: }
453:
454: /**
455: * Get the index number for the primary key index on this catalog.
456: *
457: * @return a 0-based number
458: *
459: */
460: public int getPrimaryKeyIndexNumber() {
461: return SYSCOLUMNS_INDEX1_ID;
462: }
463:
464: /**
465: * Builds a list of columns suitable for creating this Catalog.
466: *
467: *
468: * @return array of SystemColumn suitable for making this catalog.
469: */
470: public SystemColumn[] buildColumnList() {
471: if (columnList != null) {
472: return columnList;
473: }
474:
475: columnList = new SystemColumn[SYSCOLUMNS_COLUMN_COUNT];
476:
477: // describe columns
478:
479: columnList[0] = new SystemColumnImpl(
480: convertIdCase(REFERENCEDID_STRING), // column name
481: SYSCOLUMNS_REFERENCEID,// column number
482: 0, // precision
483: 0, // scale
484: false, // nullability
485: "CHAR", // dataType
486: true, // built-in type
487: 36 // maxLength
488: );
489:
490: columnList[1] = new SystemColumnImpl( // SQL IDENTIFIER
491: convertIdCase(COLUMNNAME_STRING), // column name
492: SYSCOLUMNS_COLUMNNAME, // column number
493: false // nullability
494: );
495:
496: columnList[2] = new SystemColumnImpl(
497: convertIdCase("COLUMNNUMBER"), // column name
498: SYSCOLUMNS_COLUMNNUMBER, // column number
499: 0, // precision
500: 0, // scale
501: false, // nullability
502: "INTEGER", // dataType
503: true, // built-in type
504: 4 // maxLength
505: );
506:
507: columnList[3] = new SystemColumnImpl(
508: convertIdCase("COLUMNDATATYPE"), // column name
509: SYSCOLUMNS_COLUMNDATATYPE, // column number
510: 0, // precision
511: 0, // scale
512: false, // nullability
513: "org.apache.derby.catalog.TypeDescriptor", // dataType
514: false, // built-in type
515: TypeDescriptor.MAXIMUM_WIDTH_UNKNOWN // maxLength
516: );
517:
518: columnList[4] = new SystemColumnImpl(
519: convertIdCase("COLUMNDEFAULT"), // column name
520: SYSCOLUMNS_COLUMNDEFAULT, // column number
521: 0, // precision
522: 0, // scale
523: true, // nullability
524: "java.io.Serializable", // dataType
525: false, // built-in type
526: TypeDescriptor.MAXIMUM_WIDTH_UNKNOWN // maxLength
527: );
528:
529: columnList[5] = new SystemColumnImpl(
530: convertIdCase(COLUMNDEFAULTID_STRING), // column name
531: SYSCOLUMNS_COLUMNDEFAULTID,// column number
532: 0, // precision
533: 0, // scale
534: true, // nullability
535: "CHAR", // dataType
536: true, // built-in type
537: 36 // maxLength
538: );
539:
540: // new columns for autoincrement.
541: columnList[6] = new SystemColumnImpl(
542: convertIdCase("AUTOINCREMENTVALUE"), // column name
543: SYSCOLUMNS_AUTOINCREMENTVALUE, 0, 0, true, "BIGINT",
544: true, TypeId.LONGINT_MAXWIDTH);
545:
546: columnList[7] = new SystemColumnImpl(
547: convertIdCase("AUTOINCREMENTSTART"), // column name
548: SYSCOLUMNS_AUTOINCREMENTSTART, 0, 0, true, "BIGINT",
549: true, TypeId.LONGINT_MAXWIDTH);
550:
551: columnList[8] = new SystemColumnImpl(
552: convertIdCase("AUTOINCREMENTINC"), // column name
553: SYSCOLUMNS_AUTOINCREMENTINC, 0, 0, true, "BIGINT",
554: true, TypeId.LONGINT_MAXWIDTH);
555:
556: return columnList;
557: }
558: }
|