--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.sql.catalog.SYSCOLUMNSRowFactory\r
+\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to you under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+*/\r
+\r
+package org.apache.derby.impl.sql.catalog;\r
+\r
+import java.sql.Types;\r
+import java.util.Properties;\r
+\r
+import org.apache.derby.catalog.UUID;\r
+import org.apache.derby.catalog.types.BaseTypeIdImpl;\r
+import org.apache.derby.catalog.types.DefaultInfoImpl;\r
+import org.apache.derby.catalog.types.TypeDescriptorImpl;\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.reference.Property;\r
+import org.apache.derby.iapi.services.monitor.Monitor;\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+import org.apache.derby.iapi.services.uuid.UUIDFactory;\r
+import org.apache.derby.iapi.sql.dictionary.CatalogRowFactory;\r
+import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor;\r
+import org.apache.derby.iapi.sql.dictionary.DataDescriptorGenerator;\r
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;\r
+import org.apache.derby.iapi.sql.dictionary.SystemColumn;\r
+import org.apache.derby.iapi.sql.dictionary.TupleDescriptor;\r
+import org.apache.derby.iapi.sql.dictionary.UniqueTupleDescriptor;\r
+import org.apache.derby.iapi.sql.execute.ExecRow;\r
+import org.apache.derby.iapi.sql.execute.ExecutionFactory;\r
+import org.apache.derby.iapi.store.raw.RawStoreFactory;\r
+import org.apache.derby.iapi.types.DataTypeDescriptor;\r
+import org.apache.derby.iapi.types.DataValueDescriptor;\r
+import org.apache.derby.iapi.types.DataValueFactory;\r
+import org.apache.derby.iapi.types.SQLChar;\r
+import org.apache.derby.iapi.types.SQLInteger;\r
+import org.apache.derby.iapi.types.SQLLongint;\r
+import org.apache.derby.iapi.types.SQLVarchar;\r
+import org.apache.derby.iapi.types.TypeId;\r
+import org.apache.derby.impl.sql.compile.ColumnDefinitionNode;\r
+\r
+/**\r
+ * Factory for creating a SYSCOLUMNS row.\r
+ *\r
+ *\r
+ * @version 0.1\r
+ */\r
+\r
+public class SYSCOLUMNSRowFactory extends CatalogRowFactory\r
+{\r
+ static final String TABLENAME_STRING = "SYSCOLUMNS";\r
+\r
+ protected static final int SYSCOLUMNS_COLUMN_COUNT = 9;\r
+ /* Column #s for syscolumns (1 based) */\r
+\r
+ //TABLEID is an obsolete name, it is better to use \r
+ //REFERENCEID, but to make life easier you can use either\r
+ protected static final int SYSCOLUMNS_TABLEID = 1;\r
+ protected static final int SYSCOLUMNS_REFERENCEID = 1;\r
+ protected static final int SYSCOLUMNS_COLUMNNAME = 2;\r
+ protected static final int SYSCOLUMNS_COLUMNNUMBER = 3;\r
+ protected static final int SYSCOLUMNS_COLUMNDATATYPE = 4;\r
+ protected static final int SYSCOLUMNS_COLUMNDEFAULT = 5;\r
+ protected static final int SYSCOLUMNS_COLUMNDEFAULTID = 6;\r
+ protected static final int SYSCOLUMNS_AUTOINCREMENTVALUE = 7;\r
+ protected static final int SYSCOLUMNS_AUTOINCREMENTSTART = 8;\r
+ protected static final int SYSCOLUMNS_AUTOINCREMENTINC = 9;\r
+\r
+ //private static final String SYSCOLUMNS_INDEX1_NAME = "SYSCOLUMNS_INDEX1";\r
+ protected static final int SYSCOLUMNS_INDEX1_ID = 0;\r
+\r
+ //private static final String SYSCOLUMNS_INDEX2_NAME = "SYSCOLUMNS_INDEX2";\r
+ protected static final int SYSCOLUMNS_INDEX2_ID = 1;\r
+\r
+ private static final boolean[] uniqueness = {\r
+ true,\r
+ false\r
+ };\r
+\r
+ private static final String[] uuids =\r
+ {\r
+ "8000001e-00d0-fd77-3ed8-000a0a0b1900" // catalog UUID\r
+ ,"80000029-00d0-fd77-3ed8-000a0a0b1900" // heap UUID\r
+ ,"80000020-00d0-fd77-3ed8-000a0a0b1900" // SYSCOLUMNS_INDEX1 UUID\r
+ ,"6839c016-00d9-2829-dfcd-000a0a411400" // SYSCOLUMNS_INDEX2 UUID\r
+ };\r
+\r
+ private static final int[][] indexColumnPositions = \r
+ {\r
+ {SYSCOLUMNS_REFERENCEID, SYSCOLUMNS_COLUMNNAME},\r
+ {SYSCOLUMNS_COLUMNDEFAULTID}\r
+ };\r
+\r
+ /////////////////////////////////////////////////////////////////////////////\r
+ //\r
+ // STATE\r
+ //\r
+ /////////////////////////////////////////////////////////////////////////////\r
+\r
+ /////////////////////////////////////////////////////////////////////////////\r
+ //\r
+ // CONSTRUCTORS\r
+ //\r
+ /////////////////////////////////////////////////////////////////////////////\r
+\r
+ SYSCOLUMNSRowFactory(UUIDFactory uuidf, ExecutionFactory ef, DataValueFactory dvf)\r
+ {\r
+ this(uuidf, ef, dvf, TABLENAME_STRING);\r
+ }\r
+\r
+ SYSCOLUMNSRowFactory(UUIDFactory uuidf, ExecutionFactory ef, DataValueFactory dvf,\r
+ String myName )\r
+ {\r
+ super(uuidf,ef,dvf);\r
+ initInfo(SYSCOLUMNS_COLUMN_COUNT, myName, indexColumnPositions, uniqueness, uuids);\r
+ }\r
+\r
+ /////////////////////////////////////////////////////////////////////////////\r
+ //\r
+ // METHODS\r
+ //\r
+ /////////////////////////////////////////////////////////////////////////////\r
+\r
+ /**\r
+ * Make a SYSCOLUMNS row\r
+ *\r
+ * @return Row suitable for inserting into SYSCOLUMNS.\r
+ *\r
+ * @exception StandardException thrown on failure\r
+ */\r
+\r
+ public ExecRow makeRow(TupleDescriptor td, TupleDescriptor parent)\r
+ throws StandardException\r
+ {\r
+ ExecRow row;\r
+ DataValueDescriptor col;\r
+\r
+ String colName = null;\r
+ String defaultID = null;\r
+ String tabID = null;\r
+ Integer colID = null;\r
+ TypeDescriptorImpl typeDesc = null;\r
+ Object defaultSerializable = null;\r
+ long autoincStart = 0;\r
+ long autoincInc = 0;\r
+ long autoincValue = 0;\r
+ //The SYSCOLUMNS table's autoinc related columns change with different\r
+ //values depending on what happened to the autoinc column, ie is the \r
+ //user adding an autoincrement column, or is user changing the existing \r
+ //autoincrement column to change it's increment value or to change it's\r
+ //start value? Following variable is used to keep track of what happened \r
+ //to the autoincrement column.\r
+ long autoinc_create_or_modify_Start_Increment = -1;\r
+\r
+ if (td != null)\r
+ {\r
+ ColumnDescriptor column = (ColumnDescriptor)td;\r
+ \r
+ /* Lots of info in the column's type descriptor */\r
+ typeDesc = column.getType().getCatalogType();\r
+\r
+ tabID = column.getReferencingUUID().toString();\r
+ colName = column.getColumnName();\r
+ colID = new Integer(column.getPosition() );\r
+ autoincStart = column.getAutoincStart();\r
+ autoincInc = column.getAutoincInc();\r
+ autoincValue = column.getAutoincValue();\r
+ autoinc_create_or_modify_Start_Increment = column.getAutoinc_create_or_modify_Start_Increment();\r
+ if (column.getDefaultInfo() != null)\r
+ {\r
+ defaultSerializable = column.getDefaultInfo();\r
+ }\r
+ else\r
+ {\r
+ defaultSerializable = column.getDefaultValue();\r
+ }\r
+ if (column.getDefaultUUID() != null)\r
+ {\r
+ defaultID = column.getDefaultUUID().toString();\r
+ }\r
+ }\r
+\r
+ /* Insert info into syscolumns */\r
+\r
+ /* RESOLVE - It would be nice to require less knowledge about syscolumns\r
+ * and have this be more table driven.\r
+ * RESOLVE - We'd like to store the DataTypeDescriptor in a column.\r
+ */\r
+\r
+ /* Build the row to insert */\r
+ row = getExecutionFactory().getValueRow(SYSCOLUMNS_COLUMN_COUNT);\r
+\r
+ /* 1st column is REFERENCEID (UUID - char(36)) */\r
+ row.setColumn(SYSCOLUMNS_REFERENCEID, new SQLChar(tabID));\r
+\r
+ /* 2nd column is COLUMNNAME (varchar(128)) */\r
+ row.setColumn(SYSCOLUMNS_COLUMNNAME, new SQLVarchar(colName));\r
+\r
+ /* 3rd column is COLUMNNUMBER (int) */\r
+ row.setColumn(SYSCOLUMNS_COLUMNNUMBER, new SQLInteger(colID));\r
+\r
+ /* 4th column is COLUMNDATATYPE */\r
+ row.setColumn(SYSCOLUMNS_COLUMNDATATYPE,\r
+ dvf.getDataValue(typeDesc));\r
+\r
+ /* 5th column is COLUMNDEFAULT */\r
+ row.setColumn(SYSCOLUMNS_COLUMNDEFAULT,\r
+ dvf.getDataValue(defaultSerializable));\r
+\r
+ /* 6th column is DEFAULTID (UUID - char(36)) */\r
+ row.setColumn(SYSCOLUMNS_COLUMNDEFAULTID, new SQLChar(defaultID));\r
+\r
+ if (autoinc_create_or_modify_Start_Increment == ColumnDefinitionNode.CREATE_AUTOINCREMENT ||\r
+ autoinc_create_or_modify_Start_Increment == ColumnDefinitionNode.MODIFY_AUTOINCREMENT_INC_VALUE)\r
+ {//user is adding an autoinc column or is changing the increment value of autoinc column\r
+ // This code also gets run when ALTER TABLE DROP COLUMN\r
+ // is used to drop a column other than the autoinc\r
+ // column, and the autoinc column gets removed from\r
+ // SYSCOLUMNS and immediately re-added with a different\r
+ // column position (to account for the dropped column).\r
+ // In this case, the autoincValue may have a\r
+ // different value than the autoincStart.\r
+ row.setColumn(SYSCOLUMNS_AUTOINCREMENTVALUE, \r
+ new SQLLongint(autoincValue));\r
+ row.setColumn(SYSCOLUMNS_AUTOINCREMENTSTART, \r
+ new SQLLongint(autoincStart));\r
+ row.setColumn(SYSCOLUMNS_AUTOINCREMENTINC, \r
+ new SQLLongint(autoincInc));\r
+ } else if (autoinc_create_or_modify_Start_Increment == ColumnDefinitionNode.MODIFY_AUTOINCREMENT_RESTART_VALUE)\r
+ {//user asked for restart with a new value, so don't change increment by and original start\r
+ //with values in the SYSCOLUMNS table. Just record the RESTART WITH value as the\r
+ //next value to be generated in the SYSCOLUMNS table\r
+ ColumnDescriptor column = (ColumnDescriptor)td;\r
+ row.setColumn(SYSCOLUMNS_AUTOINCREMENTVALUE, new SQLLongint(autoincStart));\r
+ row.setColumn(SYSCOLUMNS_AUTOINCREMENTSTART, new SQLLongint(autoincStart));\r
+ row.setColumn(SYSCOLUMNS_AUTOINCREMENTINC, new SQLLongint(\r
+ column.getTableDescriptor().getColumnDescriptor(colName).getAutoincInc()));\r
+ }\r
+ else\r
+ {\r
+ row.setColumn(SYSCOLUMNS_AUTOINCREMENTVALUE, \r
+ new SQLLongint());\r
+ row.setColumn(SYSCOLUMNS_AUTOINCREMENTSTART, \r
+ new SQLLongint());\r
+ row.setColumn(SYSCOLUMNS_AUTOINCREMENTINC,\r
+ new SQLLongint());\r
+ }\r
+ return row;\r
+ }\r
+\r
+ /**\r
+ * Get the Properties associated with creating the heap.\r
+ *\r
+ * @return The Properties associated with creating the heap.\r
+ */\r
+ public Properties getCreateHeapProperties()\r
+ {\r
+ Properties properties = new Properties();\r
+ // keep page size at 4K since its a big table\r
+ properties.put(Property.PAGE_SIZE_PARAMETER,"4096");\r
+ // default properties for system tables:\r
+ properties.put(RawStoreFactory.PAGE_RESERVED_SPACE_PARAMETER,"0");\r
+ properties.put(RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER,"1");\r
+ return properties;\r
+ }\r
+\r
+ /**\r
+ * Get the Properties associated with creating the specified index.\r
+ *\r
+ * @param indexNumber The specified index number.\r
+ *\r
+ * @return The Properties associated with creating the specified index.\r
+ */\r
+ public Properties getCreateIndexProperties(int indexNumber)\r
+ {\r
+ Properties properties = new Properties();\r
+ // keep page size for all indexes at 4K since its a big table\r
+ properties.put(Property.PAGE_SIZE_PARAMETER,"4096");\r
+ return properties;\r
+ }\r
+\r
+ ///////////////////////////////////////////////////////////////////////////\r
+ //\r
+ // ABSTRACT METHODS TO BE IMPLEMENTED BY CHILDREN OF CatalogRowFactory\r
+ //\r
+ ///////////////////////////////////////////////////////////////////////////\r
+\r
+ /**\r
+ * Make a ColumnDescriptor out of a SYSCOLUMNS row\r
+ *\r
+ * @param row a SYSCOLUMNS row\r
+ * @param parentTupleDescriptor The UniqueTupleDescriptor for the object that is tied\r
+ * to this column\r
+ * @param dd dataDictionary\r
+ *\r
+ * @return a column descriptor equivalent to a SYSCOLUMNS row\r
+ *\r
+ * @exception StandardException thrown on failure\r
+ */\r
+ public TupleDescriptor buildDescriptor(\r
+ ExecRow row,\r
+ TupleDescriptor parentTupleDescriptor,\r
+ DataDictionary dd )\r
+ throws StandardException\r
+ {\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ SanityManager.ASSERT(row.nColumns() == SYSCOLUMNS_COLUMN_COUNT, \r
+ "Wrong number of columns for a SYSCOLUMNS row");\r
+ }\r
+\r
+ int columnNumber;\r
+ String columnName;\r
+ String defaultID;\r
+ DefaultInfoImpl defaultInfo = null;\r
+ ColumnDescriptor colDesc;\r
+ BaseTypeIdImpl typeId;\r
+ TypeId wrapperTypeId;\r
+ DataValueDescriptor defaultValue = null;\r
+ UUID defaultUUID = null;\r
+ UUID uuid = null;\r
+ UUIDFactory uuidFactory = getUUIDFactory();\r
+ long autoincStart, autoincInc, autoincValue;\r
+\r
+ DataDescriptorGenerator ddg = dd.getDataDescriptorGenerator();\r
+\r
+\r
+ /*\r
+ ** We're going to be getting the UUID for this sucka\r
+ ** so make sure it is a UniqueTupleDescriptor.\r
+ */\r
+ if (parentTupleDescriptor != null)\r
+ {\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ if (!(parentTupleDescriptor instanceof UniqueTupleDescriptor))\r
+ {\r
+ SanityManager.THROWASSERT(parentTupleDescriptor.getClass().getName() \r
+ + " not instanceof UniqueTupleDescriptor"); \r
+ }\r
+ }\r
+ uuid = ((UniqueTupleDescriptor)parentTupleDescriptor).getUUID();\r
+ }\r
+ else\r
+ {\r
+ /* 1st column is REFERENCEID (char(36)) */\r
+ uuid = uuidFactory.recreateUUID(row.getColumn(SYSCOLUMNS_REFERENCEID).\r
+ getString());\r
+ }\r
+\r
+ /* NOTE: We get columns 5 and 6 next in order to work around \r
+ * a 1.3.0 HotSpot bug. (#4361550)\r
+ */\r
+\r
+ // 5th column is COLUMNDEFAULT (serialiazable)\r
+ Object object = row.getColumn(SYSCOLUMNS_COLUMNDEFAULT).getObject();\r
+ if (object instanceof DataValueDescriptor)\r
+ {\r
+ defaultValue = (DataValueDescriptor) object;\r
+ }\r
+ else if (object instanceof DefaultInfoImpl)\r
+ {\r
+ defaultInfo = (DefaultInfoImpl) object;\r
+ defaultValue = defaultInfo.getDefaultValue();\r
+ }\r
+\r
+ /* 6th column is DEFAULTID (char(36)) */\r
+ defaultID = row.getColumn(SYSCOLUMNS_COLUMNDEFAULTID).getString();\r
+\r
+ if (defaultID != null)\r
+ {\r
+ defaultUUID = uuidFactory.recreateUUID(defaultID);\r
+ }\r
+\r
+ /* 2nd column is COLUMNNAME (varchar(128)) */\r
+ columnName = row.getColumn(SYSCOLUMNS_COLUMNNAME).getString();\r
+\r
+ /* 3rd column is COLUMNNUMBER (int) */\r
+ columnNumber = row.getColumn(SYSCOLUMNS_COLUMNNUMBER).getInt();\r
+\r
+ /* 4th column is COLUMNDATATYPE */\r
+\r
+ /*\r
+ ** What is stored in the column is a TypeDescriptorImpl, which\r
+ ** points to a BaseTypeIdImpl. These are simple types that are\r
+ ** intended to be movable to the client, so they don't have\r
+ ** the entire implementation. We need to wrap them in DataTypeServices\r
+ ** and TypeId objects that contain the full implementations for\r
+ ** language processing.\r
+ */\r
+ TypeDescriptorImpl typeDescriptor = (TypeDescriptorImpl) row.getColumn(SYSCOLUMNS_COLUMNDATATYPE).\r
+ getObject();\r
+ typeId = typeDescriptor.getTypeId();\r
+\r
+ /*\r
+ ** The BaseTypeIdImpl tells what type of TypeId it is supposed to\r
+ ** be wrapped in.\r
+ */\r
+ wrapperTypeId =\r
+ (TypeId) Monitor.newInstanceFromIdentifier(typeId.wrapperTypeFormatId());\r
+ /* Wrap the BaseTypeIdImpl in a full type id */\r
+ wrapperTypeId.setNestedTypeId(typeId);\r
+\r
+ /* Wrap the TypeDescriptorImpl in a full DataTypeDescriptor */\r
+ DataTypeDescriptor dataTypeServices = new DataTypeDescriptor(typeDescriptor,\r
+ wrapperTypeId);\r
+\r
+ /* 7th column is AUTOINCREMENTVALUE (long) */\r
+ autoincValue = row.getColumn(SYSCOLUMNS_AUTOINCREMENTVALUE).getLong();\r
+\r
+ /* 8th column is AUTOINCREMENTSTART (long) */\r
+ autoincStart = row.getColumn(SYSCOLUMNS_AUTOINCREMENTSTART).getLong();\r
+\r
+ /* 9th column is AUTOINCREMENTINC (long) */\r
+ autoincInc = row.getColumn(SYSCOLUMNS_AUTOINCREMENTINC).getLong();\r
+\r
+ DataValueDescriptor col = row.getColumn(SYSCOLUMNS_AUTOINCREMENTSTART);\r
+ autoincStart = col.getLong();\r
+\r
+ col = row.getColumn(SYSCOLUMNS_AUTOINCREMENTINC);\r
+ autoincInc = col.getLong();\r
+\r
+ colDesc = new ColumnDescriptor(columnName, columnNumber,\r
+ dataTypeServices, defaultValue, defaultInfo, uuid, \r
+ defaultUUID, autoincStart, autoincInc,\r
+ autoincValue);\r
+ return colDesc;\r
+ }\r
+\r
+ /**\r
+ * Get the index number for the primary key index on this catalog.\r
+ *\r
+ * @return a 0-based number\r
+ *\r
+ */\r
+ public int getPrimaryKeyIndexNumber()\r
+ {\r
+ return SYSCOLUMNS_INDEX1_ID;\r
+ }\r
+\r
+ /**\r
+ * Builds a list of columns suitable for creating this Catalog.\r
+ *\r
+ *\r
+ * @return array of SystemColumn suitable for making this catalog.\r
+ */\r
+ public SystemColumn[] buildColumnList()\r
+ {\r
+ \r
+ return new SystemColumn[] {\r
+ SystemColumnImpl.getUUIDColumn("REFERENCEID", false),\r
+ SystemColumnImpl.getIdentifierColumn("COLUMNNAME", false),\r
+ SystemColumnImpl.getColumn("COLUMNNUMBER", Types.INTEGER, false),\r
+ SystemColumnImpl.getJavaColumn("COLUMNDATATYPE",\r
+ "org.apache.derby.catalog.TypeDescriptor", false),\r
+ SystemColumnImpl.getJavaColumn("COLUMNDEFAULT",\r
+ "java.io.Serializable", true),\r
+ SystemColumnImpl.getUUIDColumn("COLUMNDEFAULTID", true),\r
+ \r
+ SystemColumnImpl.getColumn("AUTOINCREMENTVALUE", Types.BIGINT, true),\r
+ SystemColumnImpl.getColumn("AUTOINCREMENTSTART", Types.BIGINT, true),\r
+ SystemColumnImpl.getColumn("AUTOINCREMENTINC", Types.BIGINT, true),\r
+\r
+ };\r
+ }\r
+}\r