Npgsql.Schema.DbColumnSchemaGenerator.GetColumnSchema C# (CSharp) Method

GetColumnSchema() private method

private GetColumnSchema ( ) : ReadOnlyCollection
return ReadOnlyCollection
        internal ReadOnlyCollection<NpgsqlDbColumn> GetColumnSchema()
        {
            var fields = _rowDescription.Fields;
            if (fields.Count == 0)
                return new List<NpgsqlDbColumn>().AsReadOnly();

            var result = new List<NpgsqlDbColumn>(fields.Count);
            for (var i = 0; i < fields.Count; i++)
                result.Add(null);
            var populatedColumns = 0;

            // We have two types of fields - those which correspond to actual database columns
            // and those that don't (e.g. SELECT 8). For the former we load lots of info from
            // the backend (if fetchAdditionalInfo is true), for the latter we only have the RowDescription

            var columnFieldFilter = _rowDescription.Fields
                .Where(f => f.TableOID != 0)  // Only column fields
                .Select(c => $"(attr.attrelid={c.TableOID} AND attr.attnum={c.ColumnAttributeNumber})")
                .Join(" OR ");

            if (_fetchAdditionalInfo && columnFieldFilter != "")
            {
                var query = string.Format(GetColumnsQuery, columnFieldFilter);

#if NET45 || NET451
                using (var connection = (NpgsqlConnection)((ICloneable)_connection).Clone())
#else
                using (var connection = _connection.Clone())
#endif
                {
                    connection.Open();

                    using (var cmd = new NpgsqlCommand(query, connection))
                    using (var reader = cmd.ExecuteReader())
                    {
                        for (; reader.Read(); populatedColumns++)
                        {
                            var column = LoadColumnDefinition(reader);

                            var ordinal = fields.FindIndex(f => f.TableOID == column.TableOID && f.ColumnAttributeNumber - 1 == column.ColumnAttributeNumber);
                            Contract.Assert(ordinal >= 0);
                            var field = fields[ordinal];
                            Contract.Assert(field.Name == column.ColumnName);

                            // The column's ordinal is with respect to the resultset, not its table
                            column.ColumnOrdinal = ordinal;

                            result[ordinal] = column;
                        }
                    }

                    if (populatedColumns == fields.Count)
                    {
                        // All columns were regular table columns that got loaded, we're done
                        Contract.Assert(result.All(c => c != null));
                        return result.AsReadOnly();
                    }
                }
            }

            // We had some fields which don't correspond to regular table columns (or fetchAdditionalInfo is false).
            // Fill in whatever info we have from the RowDescription itself
            for (var i = 0; i < fields.Count; i++)
            {
                if (result[i] != null)
                    continue;
                var column = SetUpNonColumnField(fields[i]);
                column.ColumnOrdinal = i;
                result[i] = column;
                populatedColumns++;
            }

            if (populatedColumns != fields.Count)
                throw new NpgsqlException("Could not load all columns for the resultset");

            return result.AsReadOnly();
        }