private void BuildInformation(DataTable schemaTable)
        {
            DBSchemaRow[] rows = DBSchemaRow.GetSortedSchemaRows(schemaTable); // MDAC 60609
            if ((null == rows) || (0 == rows.Length))
            {
                throw ADP.DynamicSQLNoTableInfo();
            }

            string baseServerName  = ""; // MDAC 72721, 73599
            string baseCatalogName = "";
            string baseSchemaName  = "";
            string baseTableName   = null;

            for (int i = 0; i < rows.Length; ++i)
            {
                DBSchemaRow row       = rows[i];
                string      tableName = row.BaseTableName;
                if ((null == tableName) || (0 == tableName.Length))
                {
                    rows[i] = null;
                    continue;
                }

                string serverName  = row.BaseServerName;
                string catalogName = row.BaseCatalogName;
                string schemaName  = row.BaseSchemaName;
                if (null == serverName)
                {
                    serverName = "";
                }
                if (null == catalogName)
                {
                    catalogName = "";
                }
                if (null == schemaName)
                {
                    schemaName = "";
                }
                if (null == baseTableName)
                {
                    baseServerName  = serverName;
                    baseCatalogName = catalogName;
                    baseSchemaName  = schemaName;
                    baseTableName   = tableName;
                }
                else if ((0 != ADP.SrcCompare(baseTableName, tableName)) ||
                         (0 != ADP.SrcCompare(baseSchemaName, schemaName)) ||
                         (0 != ADP.SrcCompare(baseCatalogName, catalogName)) ||
                         (0 != ADP.SrcCompare(baseServerName, serverName)))
                {
                    throw ADP.DynamicSQLJoinUnsupported();
                }
            }
            if (0 == baseServerName.Length)
            {
                baseServerName = null;
            }
            if (0 == baseCatalogName.Length)
            {
                baseServerName  = null;
                baseCatalogName = null;
            }
            if (0 == baseSchemaName.Length)
            {
                baseServerName  = null;
                baseCatalogName = null;
                baseSchemaName  = null;
            }
            if ((null == baseTableName) || (0 == baseTableName.Length))
            {
                throw ADP.DynamicSQLNoTableInfo();
            }

            if (!ADP.IsEmpty(this.quotePrefix) && (-1 != baseTableName.IndexOf(quotePrefix)))
            {
                throw ADP.DynamicSQLNestedQuote(baseTableName, quotePrefix);
            }
            if (!ADP.IsEmpty(this.quoteSuffix) && (-1 != baseTableName.IndexOf(quoteSuffix)))
            {
                throw ADP.DynamicSQLNestedQuote(baseTableName, quoteSuffix);
            }

            System.Text.StringBuilder quoted = new System.Text.StringBuilder();
            if (null != baseServerName)
            {
                quoted.Append(QuotePrefix);
                quoted.Append(baseServerName);
                quoted.Append(QuoteSuffix);
                quoted.Append(".");
            }
            if (null != baseCatalogName)
            {
                quoted.Append(QuotePrefix);
                quoted.Append(baseCatalogName);
                quoted.Append(QuoteSuffix);
                quoted.Append(".");
            }
            if (null != baseSchemaName)
            {
                quoted.Append(QuotePrefix);
                quoted.Append(baseSchemaName);
                quoted.Append(QuoteSuffix);
                quoted.Append(".");
            }
            quoted.Append(QuotePrefix);
            quoted.Append(baseTableName);
            quoted.Append(QuoteSuffix);
            this.quotedBaseTableName = quoted.ToString();
            this.dbSchemaRows        = rows;
        }
        private void SetupSchemaWithKeyInfo(MissingMappingAction mappingAction, MissingSchemaAction schemaAction, bool gettingData, DataColumn parentChapterColumn, object chapterValue)
        {
#if DEBUG
            Debug.Assert(null != schemaTable, "null schematable");
            if (AdapterSwitches.DataSchema.TraceVerbose)
            {
                ADP.TraceDataTable("SetupSchema", schemaTable);
            }
#endif
            DBSchemaRow[] schemaRows = DBSchemaRow.GetSortedSchemaRows(schemaTable); // MDAC 60609
            Debug.Assert(null != schemaRows, "SchemaSetup - null DBSchemaRow[]");

            int count = schemaRows.Length;
            if (0 == count)
            {
                this.dataTable = null;
                return;
            }

            bool         addPrimaryKeys = (0 == this.dataTable.PrimaryKey.Length); // MDAC 67033
            DataColumn[] keys           = null;
            int          keyCount       = 0;
            bool         isPrimary      = true; // assume key info (if any) is about a primary key

            int[]  columnIndexMap  = null;
            bool[] chapterIndexMap = null;

            int mappingCount = 0;
            GenerateFieldNames(count);

            DataColumnCollection columnCollection = null;
            for (int sortedIndex = 0; sortedIndex < count; ++sortedIndex)
            {
                DBSchemaRow schemaRow = schemaRows[sortedIndex];

                int unsortedIndex = schemaRow.UnsortedIndex; // MDAC 67050

                DataColumnMapping columnMapping = null;
                Type       fieldType            = schemaRow.DataType;
                DataColumn dataColumn           = null;

                if (!schemaRow.IsHidden)
                {
                    columnMapping = tableMapping.GetColumnMappingBySchemaAction(fieldNames[sortedIndex], mappingAction);
                }

                bool ischapter = false;
                if ((null != columnMapping) && typeof(IDataReader).IsAssignableFrom(fieldType))
                {
                    if (null == chapterIndexMap)
                    {
                        chapterIndexMap = new bool[count];
                    }
                    chapterIndexMap[unsortedIndex] = ischapter = true;

                    fieldType = typeof(Int32);
                }

                if (columnMapping != null)
                {
                    dataColumn = columnMapping.GetDataColumnBySchemaAction(this.dataTable, fieldType, schemaAction);
                }

                if (null == dataColumn)
                {
                    if (null == columnIndexMap)
                    {
                        columnIndexMap = CreateIndexMap(count, unsortedIndex);
                    }
                    columnIndexMap[unsortedIndex] = -1;

                    // if the column is not mapped and it is a key, then don't add any key information
                    if (schemaRow.IsKey)
                    {
#if DEBUG
                        if (AdapterSwitches.DataSchema.TraceVerbose)
                        {
                            Debug.WriteLine("SetupSchema: partial primary key detected");
                        }
#endif
                        addPrimaryKeys = false; // don't add any future keys now
                        keys           = null;  // get rid of any keys we've seen
                    }
                    continue;                   // null means ignore (mapped to nothing)
                }

                if (ischapter)
                {
                    if (null == dataColumn.Table)
                    {
                        dataColumn.AllowDBNull   = false;
                        dataColumn.AutoIncrement = true;
                        dataColumn.ReadOnly      = true;
                    }
                    else if (!dataColumn.AutoIncrement)
                    {
                        throw ADP.FillChapterAutoIncrement();
                    }
                }
                else  // MDAC 67033
                {
                    if (schemaRow.IsAutoIncrement && IsAutoIncrementType(fieldType))
                    {
                        // CONSIDER: use T-SQL "IDENT_INCR('table_or_view')" and "IDENT_SEED('table_or_view')"
                        //           functions to obtain the actual increment and seed values
                        dataColumn.AutoIncrement = true;

                        if (!schemaRow.AllowDBNull)   // MDAC 71060
                        {
                            dataColumn.AllowDBNull = false;
                        }
                    }

                    // setup maxLength, only for string columns since this is all the DataSet supports
                    if (fieldType == typeof(string))
                    {
                        //@devnote:  schemaRow.Size is count of characters for string columns, count of bytes otherwise
                        dataColumn.MaxLength = schemaRow.Size;
                    }

                    if (schemaRow.IsReadOnly)
                    {
                        dataColumn.ReadOnly = true;
                    }
                    if (!schemaRow.AllowDBNull && (!schemaRow.IsReadOnly || schemaRow.IsKey))   // MDAC 71060, 72252
                    {
                        dataColumn.AllowDBNull = false;
                    }

                    if (schemaRow.IsUnique && !schemaRow.IsKey && !fieldType.IsArray)
                    {
                        // note, arrays are not comparable so only mark non-arrays as unique, ie timestamp columns
                        // are unique, but not comparable
                        dataColumn.Unique = true;

                        if (!schemaRow.AllowDBNull)   // MDAC 71060
                        {
                            dataColumn.AllowDBNull = false;
                        }
                    }
                }
                if (null == dataColumn.Table)
                {
                    if (null == columnCollection)
                    {
                        columnCollection = dataTable.Columns;
                    }
                    columnCollection.Add(dataColumn);
                }

                // The server sends us one key per table according to these rules.
                //
                // 1. If the table has a primary key, the server sends us this key.
                // 2. If the table has a primary key and a unique key, it sends us the primary key
                // 3. if the table has no primary key but has a unique key, it sends us the unique key
                //
                // In case 3, we will promote a unique key to a primary key IFF all the columns that compose
                // that key are not nullable since no columns in a primary key can be null.  If one or more
                // of the keys is nullable, then we will add a unique constraint.
                //
                if (addPrimaryKeys && schemaRow.IsKey)   // MDAC 67033
                {
                    if (keys == null)
                    {
                        keys = new DataColumn[count];
                    }
                    keys[keyCount++] = dataColumn;
#if DEBUG
                    if (AdapterSwitches.DataSchema.TraceVerbose)
                    {
                        Debug.WriteLine("SetupSchema: building list of " + ((isPrimary) ? "PrimaryKey" : "UniqueConstraint"));
                    }
#endif
                    // see case 3 above, we do want dataColumn.AllowDBNull not schemaRow.AllowDBNull
                    // otherwise adding PrimaryKey will change AllowDBNull to false
                    if (isPrimary && dataColumn.AllowDBNull)   // MDAC 72241
                    {
#if DEBUG
                        if (AdapterSwitches.DataSchema.TraceVerbose)
                        {
                            Debug.WriteLine("SetupSchema: changing PrimaryKey into UniqueContraint");
                        }
#endif
                        isPrimary = false;
                    }
                }

                if (null != columnIndexMap)
                {
                    columnIndexMap[unsortedIndex] = dataColumn.Ordinal;
                }
                else if (unsortedIndex != dataColumn.Ordinal)
                {
                    columnIndexMap = CreateIndexMap(count, unsortedIndex);
                    columnIndexMap[unsortedIndex] = dataColumn.Ordinal;
                }
                mappingCount++;
            }

            bool       addDataRelation = false;
            DataColumn chapterColumn   = null;
            if (null != chapterValue)   // add the extra column in the child table
            {
                DataColumnMapping columnMapping = tableMapping.GetColumnMappingBySchemaAction(tableMapping.SourceTable, mappingAction);
                if (null != columnMapping)
                {
                    Type fieldType = chapterValue.GetType();
                    chapterColumn = columnMapping.GetDataColumnBySchemaAction(this.dataTable, fieldType, schemaAction);
                    if (null != chapterColumn)
                    {
                        if (null == chapterColumn.Table)
                        {
                            chapterColumn.ReadOnly    = true; // MDAC 71878
                            chapterColumn.AllowDBNull = false;

                            if (null == columnCollection)
                            {
                                columnCollection = dataTable.Columns;
                            }
                            columnCollection.Add(chapterColumn);
                            addDataRelation = (null != parentChapterColumn);
                        }
                        mappingCount++;
                    }
                }
            }

            object[] dataValues = null;
            if (0 < mappingCount)
            {
                if ((null != this.dataSet) && null == this.dataTable.DataSet)
                {
                    this.dataSet.Tables.Add(this.dataTable);
                }
                // setup the key
                if (addPrimaryKeys && (null != keys))   // MDAC 67033
                {
                    if (keyCount < keys.Length)
                    {
                        keys = ResizeColumnArray(keys, keyCount);
                    }

                    // MDAC 66188
                    if (isPrimary)
                    {
#if DEBUG
                        if (AdapterSwitches.DataSchema.TraceVerbose)
                        {
                            Debug.WriteLine("SetupSchema: set_PrimaryKey");
                        }
#endif
                        this.dataTable.PrimaryKey = keys;
                    }
                    else
                    {
                        UniqueConstraint     unique      = new UniqueConstraint("", keys);
                        ConstraintCollection constraints = this.dataTable.Constraints;
                        int constraintCount = constraints.Count;
                        for (int i = 0; i < constraintCount; ++i)
                        {
                            if (unique.Equals(constraints[i]))
                            {
#if DEBUG
                                if (AdapterSwitches.DataSchema.TraceVerbose)
                                {
                                    Debug.WriteLine("SetupSchema: duplicate Contraint detected");
                                }
#endif
                                unique = null;
                                break;
                            }
                        }
                        if (null != unique)
                        {
#if DEBUG
                            if (AdapterSwitches.DataSchema.TraceVerbose)
                            {
                                Debug.WriteLine("SetupSchema: adding new UniqueConstraint");
                            }
#endif
                            constraints.Add(unique);
                        }
                    }
                }
                if (gettingData)
                {
                    if (null == columnCollection)
                    {
                        columnCollection = dataTable.Columns;
                    }
                    _indexMap   = columnIndexMap;
                    _chapterMap = chapterIndexMap;
                    dataValues  = SetupMapping(count, columnCollection, chapterColumn, chapterValue);
                }
#if DEBUG
                else
                {
                    this.mappedMode = -1;
                }
#endif
            }
            else
            {
                this.dataTable = null;
            }
            if (addDataRelation)
            {
                AddRelation(parentChapterColumn, chapterColumn);
            }
            _readerDataValues = dataValues;
        }