--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.store.access.btree.BTree\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.store.access.btree;\r
+\r
+import org.apache.derby.iapi.reference.SQLState;\r
+\r
+import org.apache.derby.iapi.services.io.ArrayInputStream;\r
+import org.apache.derby.iapi.services.io.FormatableBitSet;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.iapi.services.io.FormatIdUtil;\r
+import org.apache.derby.iapi.services.io.Storable;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.store.access.conglomerate.TransactionManager;\r
+import org.apache.derby.iapi.store.access.ConglomerateController;\r
+import org.apache.derby.iapi.store.access.DynamicCompiledOpenConglomInfo;\r
+import org.apache.derby.iapi.store.access.RowLocationRetRowSource;\r
+import org.apache.derby.iapi.store.access.StaticCompiledOpenConglomInfo;\r
+\r
+import org.apache.derby.iapi.store.raw.LockingPolicy;\r
+import org.apache.derby.iapi.store.raw.RawStoreFactory;\r
+import org.apache.derby.iapi.store.raw.ContainerHandle;\r
+import org.apache.derby.iapi.store.raw.Transaction;\r
+import org.apache.derby.iapi.store.raw.ContainerKey;\r
+\r
+import org.apache.derby.iapi.types.DataValueDescriptor;\r
+\r
+import org.apache.derby.impl.store.access.conglomerate.ConglomerateUtil;\r
+import org.apache.derby.impl.store.access.conglomerate.GenericConglomerate;\r
+import org.apache.derby.impl.store.access.conglomerate.OpenConglomerateScratchSpace;\r
+import org.apache.derby.impl.store.access.conglomerate.TemplateRow;\r
+\r
+import java.io.IOException;\r
+import java.io.ObjectOutput;\r
+import java.io.ObjectInput;\r
+\r
+import java.util.Properties;\r
+\r
+import org.apache.derby.iapi.services.io.ArrayUtil;\r
+\r
+/**\r
+\r
+ A b-tree object corresponds to an instance of a b-tree conglomerate. It \r
+ contains the static information about a conglomerate which is built at \r
+ create conglomerate time.\r
+ <p>\r
+ This generic implementation is expected to be extended by the concreate\r
+ implementations.\r
+ <P>\r
+ The fields are set when the conglomerate is created and never changed \r
+ thereafter. When alter table is supported then it will change under the\r
+ control of a table level lock.\r
+ <p>\r
+ They have package scope because they're read by the scans and controllers.\r
+ <p>\r
+ A table of all conglomerates in the system is maintained by the accessmanager.\r
+ A cache of conglomerates is maintained in the accessmanager, and references\r
+ to the read only objects are handed out. A copy of the Conglomerate\r
+ object is kept in the control row of the root page, so that during logical\r
+ undo this information can be read without needing to access the possibly\r
+ corrupt table maintained by the access manager.\r
+**/\r
+\r
+public abstract class BTree extends GenericConglomerate\r
+{\r
+ /**************************************************************************\r
+ * Public Constants of BTree class:\r
+ **************************************************************************\r
+ */\r
+\r
+ /**\r
+ * The page number of the root page is always at the fixed page number:\r
+ * ROOTPAGEID. This means that given an open container, during logical\r
+ * undo one can always find the root page and look up the conglomerate\r
+ * information.\r
+ **/\r
+ public static final long ROOTPAGEID = ContainerHandle.FIRST_PAGE_NUMBER;\r
+\r
+ /** \r
+ Property name for the maximum number of rows to place in a btree page (leaf\r
+ or branch). Equal to 'derby.access.btreeMaxRowPerPage'. Used by tests\r
+ and debugging to exactly control split points, and to make it easier to test\r
+ tall trees without needing lots of data.\r
+ */\r
+ public static final String PROPERTY_MAX_ROWS_PER_PAGE_PARAMETER = \r
+ (SanityManager.DEBUG ? "derby.access.btreeMaxRowPerPage" : null);\r
+\r
+ /* properties of a btree see create(). */\r
+ public static final String PROPERTY_ALLOWDUPLICATES = "allowDuplicates";\r
+ public static final String PROPERTY_NKEYFIELDS = "nKeyFields";\r
+ public static final String PROPERTY_NUNIQUECOLUMNS = "nUniqueColumns";\r
+ public static final String PROPERTY_PARENTLINKS = "maintainParentLinks";\r
+\r
+\r
+\r
+ /**************************************************************************\r
+ * Protected Fields of BTree class:\r
+ **************************************************************************\r
+ */\r
+\r
+ /**\r
+ The id of the container in which this b-tree is stored. \r
+ **/\r
+ protected ContainerKey id;\r
+\r
+ /**\r
+ The number of key fields.\r
+ **/\r
+ protected int nKeyFields;\r
+\r
+ /**\r
+ The number of uniqueness columns. These are the columns that\r
+ are considered for the purpose of detecting duplicate keys and rows.\r
+ **/\r
+ int nUniqueColumns;\r
+\r
+ /**\r
+ Whether the index allows duplicates or not.\r
+ **/\r
+ boolean allowDuplicates;\r
+\r
+ /**\r
+ Whether the parent should maintain links from child pages to their parent.\r
+ These links are only used for consistency checking purposes. They improve\r
+ consistency checking at the cost of run-time efficiency.\r
+ **/\r
+ boolean maintainParentLinks;\r
+\r
+ /**\r
+ Maximum rows per page to place on a btree leaf or nonleaf page. Used\r
+ by testing to finely control split points. Only changed for debugging\r
+ purposes.\r
+\r
+ RESOLVE (mikem) - this should not be static. Need to design a way in\r
+ debugging mode to get btree created with a persistent "maxRowsPerPage".\r
+ This hack makes all btrees get created with the "last" maxRowsPerPage \r
+ value set.\r
+ **/\r
+ static int maxRowsPerPage = Integer.MAX_VALUE;\r
+\r
+ /**\r
+ Format id of the conglomerate.\r
+ **/\r
+ protected int conglom_format_id;\r
+\r
+ /**\r
+ The array of format id's, one for each column in the template.\r
+ **/\r
+ protected int[] format_ids;\r
+\r
+\r
+ //columns sorting order information\r
+ // true - Ascending Order ; false -Descending Order\r
+ protected boolean[] ascDescInfo;\r
+\r
+ /**\r
+ The array of collation id's for each column in the template.\r
+ **/\r
+ protected int[] collation_ids;\r
+\r
+\r
+ /*\r
+ ** Private Methods of BTree.\r
+ */\r
+\r
+ /*\r
+ ** Public Methods of BTree.\r
+ */\r
+\r
+\r
+ /**************************************************************************\r
+ * Abstract Protected locking methods of BTree:\r
+ * getBtreeLockingPolicy\r
+ * lockScan\r
+ * unlockScan\r
+ * lockPreviousRow\r
+ * lockRowOnPage\r
+ * lockRow\r
+ * lockTable\r
+ **************************************************************************\r
+ */\r
+\r
+ /**\r
+ * Create a new btree locking policy from scratch.\r
+ *\r
+ * @exception StandardException Standard exception policy.\r
+ **/\r
+ abstract protected BTreeLockingPolicy getBtreeLockingPolicy(\r
+ Transaction rawtran,\r
+ int lock_level,\r
+ int mode,\r
+ int isolation_level,\r
+ ConglomerateController base_cc,\r
+ OpenBTree open_btree)\r
+ throws StandardException;\r
+\r
+ /**\r
+ * Lock the base table.\r
+ * <p>\r
+ * Assumes that segment of the base container is the same as the segment\r
+ * of the btree segment.\r
+ * <p>\r
+ * RESOLVE - we really want to get the lock without opening the container.\r
+ * raw store will be providing this.\r
+ *\r
+ * @param xact_manager Transaction to associate the lock with.\r
+ *\r
+ * @exception StandardException Standard exception policy.\r
+ **/\r
+ abstract public ConglomerateController lockTable(\r
+ TransactionManager xact_manager,\r
+ int open_mode,\r
+ int lock_level,\r
+ int isolation_level)\r
+ throws StandardException;\r
+\r
+\r
+ /**************************************************************************\r
+ * Private/Protected methods of BTree:\r
+ **************************************************************************\r
+ */\r
+\r
+\r
+ /**\r
+ * Create a branch row template for this conglomerate.\r
+ * <p>\r
+ * Reads the format id's of each of the columns and manufactures object of\r
+ * the given type for each. It then uses these "empty" objects to create\r
+ * a template row. The object passed in is then added to the last column\r
+ * of the row.\r
+ *\r
+ * @return The new template.\r
+ *\r
+ * @exception StandardException Standard exception policy.\r
+ **/\r
+ final DataValueDescriptor[] createBranchTemplate(\r
+ Transaction rawtran,\r
+ DataValueDescriptor page_ptr)\r
+ throws StandardException\r
+ {\r
+ return(\r
+ TemplateRow.newBranchRow(\r
+ rawtran, format_ids, collation_ids, page_ptr));\r
+ }\r
+\r
+\r
+ /**************************************************************************\r
+ * Public methods of BTree:\r
+ **************************************************************************\r
+ */\r
+\r
+ /**\r
+ * Create a template for this conglomerate.\r
+ * <p>\r
+ * Reads the format id's of each of the columns and manufactures object of\r
+ * the given type for each. It then uses these "empty" objects to create\r
+ * a template row.\r
+ * <p>\r
+ * This method is public so that B2IUndo() can call it.\r
+ *\r
+ * @return The new template.\r
+ *\r
+ * @exception StandardException Standard exception policy.\r
+ **/\r
+ final public DataValueDescriptor[] createTemplate(\r
+ Transaction rawtran)\r
+ throws StandardException\r
+ {\r
+ if (SanityManager.DEBUG)\r
+ SanityManager.ASSERT(format_ids != null);\r
+\r
+ return(TemplateRow.newRow(\r
+ rawtran, \r
+ (FormatableBitSet) null, format_ids, collation_ids));\r
+ }\r
+\r
+ /**\r
+ * Is this a "unique" index?\r
+ **/\r
+ final public boolean isUnique()\r
+ {\r
+ return(nKeyFields != nUniqueColumns);\r
+ }\r
+\r
+ /**************************************************************************\r
+ * Public Methods of Conglomerate Interface:\r
+ **************************************************************************\r
+ */\r
+\r
+ /**\r
+ * Add a column to the conglomerate.\r
+ * <p>\r
+ * Currently B2I does not support this operation.\r
+ * input template column. \r
+ * \r
+ * @param xact_manager Transaction to associate the lock with.\r
+ * @param column_id The column number to add this column at.\r
+ * @param template_column An instance of the column to be added to table.\r
+ *\r
+ * @exception StandardException Standard exception policy.\r
+ **/\r
+ public void addColumn(\r
+ TransactionManager xact_manager,\r
+ int column_id,\r
+ Storable template_column,\r
+ int collation_id)\r
+ throws StandardException\r
+ {\r
+ throw StandardException.newException(\r
+ SQLState.BTREE_UNIMPLEMENTED_FEATURE);\r
+ }\r
+\r
+ /**\r
+ * Get the id of the container of the conglomerate.\r
+ * <p>\r
+ * Will have to change when a conglomerate could have more than one \r
+ * container. The ContainerKey is a combination of the container id\r
+ * and segment id.\r
+ *\r
+ * @return The ContainerKey.\r
+ **/\r
+ public final ContainerKey getId()\r
+ {\r
+ return(id);\r
+ }\r
+\r
+\r
+ /**\r
+ Do the generic part of creating a b-tree conglomerate. This method \r
+ is called from the concrete subclass (which may also read some properties).\r
+ <p>\r
+ This method processes all properties which are generic to all BTree's. It\r
+ creates the container for the btree.\r
+ <p>\r
+\r
+ The following properties are generic to a b-tree conglomerate. :\r
+\r
+ <UL>\r
+ <LI>"allowDuplicates" (boolean). If set to true the table will allow \r
+ rows which are duplicate in key column's 0 through (nUniqueColumns - 1).\r
+ Currently only supports "false".\r
+ This property is optional, defaults to false.\r
+ <LI>"nKeyFields" (integer) Columns 0 through (nKeyFields - 1) will be \r
+ included in key of the conglomerate.\r
+ This implementation requires that "nKeyFields" must be the same as the\r
+ number of fields in the conglomerate, including the rowLocationColumn.\r
+ Other implementations may relax this restriction to allow non-key fields\r
+ in the index.\r
+ This property is required.\r
+ <LI>"nUniqueColumns" (integer) Columns 0 through "nUniqueColumns" will be \r
+ used to check for uniqueness. So for a standard SQL non-unique index \r
+ implementation set "nUniqueColumns" to the same value as "nKeyFields"; and\r
+ for a unique index set "nUniqueColumns" to "nKeyFields" - 1 (ie. don't \r
+ include the rowLocationColumn in the uniqueness check).\r
+ This property is required.\r
+ <LI>"maintainParentLinks" (boolean)\r
+ Whether the b-tree pages maintain the page number of their parent. Only\r
+ used for consistency checking. It takes a certain amount more effort to\r
+ maintain these links, but they're really handy for ensuring that the index\r
+ is consistent.\r
+ This property is optional, defaults to true.\r
+ </UL>\r
+\r
+ @exception StandardException Thrown by underlying raw store, or thrown by\r
+ this routine on an invalid containerid.\r
+ \r
+ **/\r
+\r
+ public void create(\r
+ Transaction rawtran,\r
+ int segmentId,\r
+ long input_containerid,\r
+ DataValueDescriptor[] template,\r
+ Properties properties,\r
+ int conglom_format_id,\r
+ int tmpFlag\r
+ )\r
+ throws StandardException\r
+ {\r
+ String result_string;\r
+\r
+ if (properties == null)\r
+ {\r
+ throw(\r
+ StandardException.newException(\r
+ SQLState.BTREE_PROPERTY_NOT_FOUND, PROPERTY_NKEYFIELDS));\r
+ }\r
+\r
+ // Check input arguments\r
+ allowDuplicates = (Boolean.valueOf(\r
+ properties.getProperty(PROPERTY_ALLOWDUPLICATES, "false"))).booleanValue();\r
+\r
+ result_string = properties.getProperty(PROPERTY_NKEYFIELDS);\r
+ if (result_string == null)\r
+ {\r
+ throw(\r
+ StandardException.newException(\r
+ SQLState.BTREE_PROPERTY_NOT_FOUND, PROPERTY_NKEYFIELDS));\r
+ }\r
+ else\r
+ {\r
+ nKeyFields = Integer.parseInt(result_string);\r
+ }\r
+\r
+ result_string = properties.getProperty(PROPERTY_NUNIQUECOLUMNS);\r
+ if (result_string == null)\r
+ {\r
+ throw(StandardException.newException(\r
+ SQLState.BTREE_PROPERTY_NOT_FOUND, PROPERTY_NUNIQUECOLUMNS));\r
+ }\r
+ else\r
+ {\r
+ nUniqueColumns = Integer.parseInt(result_string);\r
+ }\r
+\r
+\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ result_string = \r
+ properties.getProperty(PROPERTY_MAX_ROWS_PER_PAGE_PARAMETER);\r
+\r
+ if (result_string != null)\r
+ {\r
+ maxRowsPerPage = Integer.parseInt(result_string);\r
+ }\r
+ }\r
+\r
+ maintainParentLinks = (Boolean.valueOf(\r
+ properties.getProperty(PROPERTY_PARENTLINKS, "true"))).booleanValue();\r
+\r
+ // RESOLVE (mikem) - true for now, if we want to support non-key \r
+ // fields eventually this assert may be wrong.\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ if (template.length != nKeyFields)\r
+ {\r
+ SanityManager.THROWASSERT(\r
+ "template.length (" + template.length +\r
+ ") expected to equal nKeyFields (" + \r
+ nKeyFields + ")");\r
+ }\r
+ SanityManager.ASSERT((nUniqueColumns == nKeyFields) || \r
+ (nUniqueColumns == (nKeyFields - 1)));\r
+ }\r
+\r
+ // get format id's from each column in template and store it in the\r
+ // conglomerate state.\r
+ format_ids = ConglomerateUtil.createFormatIds(template);\r
+\r
+ // copy the format id of the conglomerate.\r
+ this.conglom_format_id = conglom_format_id;\r
+\r
+ // Create a container for the b-tree with default page size and \r
+ // fill up pages.\r
+ properties.put(RawStoreFactory.PAGE_RESERVED_SPACE_PARAMETER, "0");\r
+ properties.put(RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER, "1");\r
+ properties.put(RawStoreFactory.PAGE_REUSABLE_RECORD_ID, "true");\r
+\r
+ long containerid = \r
+ rawtran.addContainer(\r
+ segmentId, input_containerid, \r
+ ContainerHandle.MODE_DEFAULT, properties, tmpFlag);\r
+\r
+ // Make sure the container was actually created.\r
+ // Open segment will get cleaned up when transaction is.\r
+ if (containerid <= 0)\r
+ {\r
+ throw(StandardException.newException(\r
+ SQLState.BTREE_CANT_CREATE_CONTAINER)); \r
+ }\r
+\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ if (input_containerid != ContainerHandle.DEFAULT_ASSIGN_ID)\r
+ SanityManager.ASSERT(containerid == input_containerid);\r
+ }\r
+\r
+ id = new ContainerKey(segmentId, containerid);\r
+ }\r
+\r
+ /**\r
+ Drop this btree.\r
+ This must be done by a concrete implementation.\r
+ @see org.apache.derby.iapi.store.access.conglomerate.Conglomerate#drop\r
+\r
+ @exception StandardException Standard exception policy.\r
+ **/\r
+ public abstract void drop(TransactionManager xact_manager)\r
+ throws StandardException;\r
+\r
+ /**\r
+ Load a b-tree. This must be done by a concrete implementation.\r
+ @see org.apache.derby.iapi.store.access.conglomerate.Conglomerate#load\r
+\r
+ @exception StandardException Standard exception policy.\r
+ **/\r
+ public abstract long load(\r
+ TransactionManager xact_manager,\r
+ boolean createConglom,\r
+ RowLocationRetRowSource rowSource)\r
+ throws StandardException;\r
+\r
+ public long getContainerid()\r
+ {\r
+ return(this.id.getContainerId());\r
+ }\r
+\r
+ /**\r
+ * Return dynamic information about the conglomerate to be dynamically \r
+ * reused in repeated execution of a statement.\r
+ * <p>\r
+ * The dynamic info is a set of variables to be used in a given \r
+ * ScanController or ConglomerateController. It can only be used in one \r
+ * controller at a time. It is up to the caller to insure the correct \r
+ * thread access to this info. The type of info in this is a scratch \r
+ * template for btree traversal, other scratch variables for qualifier \r
+ * evaluation, ...\r
+ * <p>\r
+ *\r
+ * @return The dynamic information.\r
+ *\r
+ * @param conglomId The identifier of the conglomerate to open.\r
+ *\r
+ * @exception StandardException Standard exception policy.\r
+ **/\r
+ public DynamicCompiledOpenConglomInfo getDynamicCompiledConglomInfo(\r
+ long conglomId)\r
+ throws StandardException\r
+ {\r
+ return(new OpenConglomerateScratchSpace(format_ids, collation_ids));\r
+ }\r
+\r
+\r
+ /**\r
+ * Is this conglomerate temporary?\r
+ * <p>\r
+ *\r
+ * @return whether conglomerate is temporary or not.\r
+ **/\r
+ public boolean isTemporary()\r
+ {\r
+ return (id.getSegmentId() == ContainerHandle.TEMPORARY_SEGMENT);\r
+ }\r
+\r
+ /**\r
+ Open a b-tree controller.\r
+ This must be done by a concrete implementation.\r
+ @see org.apache.derby.iapi.store.access.conglomerate.Conglomerate#open\r
+\r
+ @exception StandardException Standard exception policy.\r
+ **/\r
+ public abstract ConglomerateController open(\r
+ TransactionManager xact_manager,\r
+ Transaction rawtran,\r
+ boolean hold,\r
+ int open_mode,\r
+ int lock_level,\r
+ LockingPolicy locking_policy,\r
+ StaticCompiledOpenConglomInfo static_info,\r
+ DynamicCompiledOpenConglomInfo dynamic_info)\r
+ throws StandardException;\r
+\r
+\r
+\r
+ /**************************************************************************\r
+ * Public Methods of Storable Interface (via Conglomerate):\r
+ * This class is responsible for re/storing its own state.\r
+ **************************************************************************\r
+ */\r
+\r
+\r
+ /**\r
+ Return whether the value is null or not.\r
+ The containerid being zero is what determines nullness; subclasses\r
+ are not expected to override this method.\r
+ @see org.apache.derby.iapi.services.io.Storable#isNull\r
+ **/\r
+ public boolean isNull()\r
+ {\r
+ return id == null;\r
+ }\r
+\r
+ /**\r
+ Restore the in-memory representation to the null value.\r
+ The containerid being zero is what determines nullness; subclasses\r
+ are not expected to override this method.\r
+\r
+ @see org.apache.derby.iapi.services.io.Storable#restoreToNull\r
+ **/\r
+ public void restoreToNull()\r
+ {\r
+ id = null;\r
+ }\r
+\r
+ /**\r
+ Restore the in-memory representation from the stream.\r
+\r
+ @exception ClassNotFoundException Thrown if the stored representation is\r
+ serialized and a class named in the stream could not be found.\r
+\r
+ @exception IOException thrown by readObject()\r
+\r
+ \r
+ @see java.io.Externalizable#readExternal\r
+ */\r
+ public void readExternal(ObjectInput in) \r
+ throws IOException, ClassNotFoundException\r
+ {\r
+ // read in the conglomerate format id.\r
+ conglom_format_id = FormatIdUtil.readFormatIdInteger(in);\r
+\r
+ // XXX (nat) need to improve error handling\r
+ long containerid = in.readLong();\r
+ int segmentid = in.readInt();\r
+ nKeyFields = in.readInt();\r
+ nUniqueColumns = in.readInt();\r
+ allowDuplicates = in.readBoolean();\r
+ maintainParentLinks = in.readBoolean();\r
+\r
+ // read in the array of format id's\r
+ format_ids = ConglomerateUtil.readFormatIdArray(this.nKeyFields, in);\r
+\r
+ id = new ContainerKey(segmentid, containerid);\r
+ }\r
+\r
+ public void readExternalFromArray(ArrayInputStream in) \r
+ throws IOException, ClassNotFoundException\r
+ {\r
+ // read in the conglomerate format id.\r
+ conglom_format_id = FormatIdUtil.readFormatIdInteger(in);\r
+\r
+ // XXX (nat) need to improve error handling\r
+ long containerid = in.readLong();\r
+ int segmentid = in.readInt();\r
+ nKeyFields = in.readInt();\r
+ nUniqueColumns = in.readInt();\r
+ allowDuplicates = in.readBoolean();\r
+ maintainParentLinks = in.readBoolean();\r
+\r
+ // read in the array of format id's\r
+ format_ids = ConglomerateUtil.readFormatIdArray(this.nKeyFields, in);\r
+\r
+ id = new ContainerKey(segmentid, containerid);\r
+ }\r
+\r
+ \r
+ /**\r
+ Store the stored representation of the column value in the stream.\r
+ It might be easier to simply store the properties - which would certainly\r
+ make upgrading easier.\r
+\r
+ @exception IOException thrown by writeObject()\r
+\r
+ */\r
+ public void writeExternal(ObjectOutput out) \r
+ throws IOException\r
+ {\r
+ FormatIdUtil.writeFormatIdInteger(out, conglom_format_id);\r
+\r
+ out.writeLong(id.getContainerId());\r
+ out.writeInt((int) id.getSegmentId());\r
+ out.writeInt((nKeyFields));\r
+ out.writeInt((nUniqueColumns));\r
+ out.writeBoolean((allowDuplicates));\r
+ out.writeBoolean((maintainParentLinks));\r
+\r
+ ConglomerateUtil.writeFormatIdArray(format_ids, out);\r
+ }\r
+\r
+ /**************************************************************************\r
+ * Public toString() Method:\r
+ **************************************************************************\r
+ */\r
+\r
+ public String toString()\r
+ {\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ return ("BTREE: containerid = " + \r
+ (this.id == null ? "null" : this.id.toString()) +\r
+ ";nKeyFields = " + nKeyFields +\r
+ ";nUniqueColumns = " + nUniqueColumns +\r
+ ";allowDuplicates = " + allowDuplicates);\r
+ }\r
+ else\r
+ {\r
+ return(super.toString());\r
+ }\r
+ }\r
+}\r