Beispiel #1
0
        internal bool TryGetByOID(uint oid, out TypeHandler handler)
        {
            if (ByOID.TryGetValue(oid, out handler))
            {
                return(true);
            }
            if (!_postgresTypes.ByOID.TryGetValue(oid, out var postgresType))
            {
                return(false);
            }

            handler = postgresType.Activate(this);
            return(true);
        }
        void LoadCompositeFields(DbDataReader reader)
        {
            PostgresCompositeType currentComposite = null;

            while (reader.Read())
            {
                var ns       = reader.GetString(reader.GetOrdinal("nspname"));
                var name     = reader.GetString(reader.GetOrdinal("typname"));
                var fullName = $"{ns}.{name}";
                if (fullName != currentComposite?.FullName)
                {
                    currentComposite = ByFullName[fullName] as PostgresCompositeType;
                    if (currentComposite == null)
                    {
                        Log.Error($"Ignoring non-composite type {fullName} when trying to load composite fields");
                        continue;
                    }
                }
                currentComposite.Fields.Add(new PostgresCompositeType.Field
                {
                    PgName  = reader.GetString(reader.GetOrdinal("attname")),
                    TypeOID = Convert.ToUInt32(reader[reader.GetOrdinal("atttypid")])
                });
            }

            // Our pass above loaded composite fields with their type OID only, do a second
            // pass to resolve them to PostgresType references (since types can come in any order)
            foreach (var compositeType in CompositeTypes.ToArray())
            {
                foreach (var field in compositeType.Fields)
                {
                    if (!ByOID.TryGetValue(field.TypeOID, out field.Type))
                    {
                        Log.Error($"Skipping composite type {compositeType.DisplayName} with field {field.PgName} with type OID {field.TypeOID}, which could not be resolved to a PostgreSQL type.");
                        Remove(compositeType);
                        CompositeTypes.Remove(compositeType);
                        goto outer;
                    }
                }
                // ReSharper disable once RedundantJumpStatement
                outer : continue;
            }
        }
 void Remove(PostgresType pgType)
 {
     ByOID.Remove(pgType.OID);
     ByName.Remove(pgType.Name);
     ByFullName.Remove(pgType.FullName);
 }
        void LoadBackendType(DbDataReader reader, NpgsqlConnector connector)
        {
            var ns   = reader.GetString(reader.GetOrdinal("nspname"));
            var name = reader.GetString(reader.GetOrdinal("typname"));
            var oid  = Convert.ToUInt32(reader[reader.GetOrdinal("oid")]);

            Debug.Assert(name != null);
            Debug.Assert(oid != 0);

            var typeChar = reader.GetString(reader.GetOrdinal("type"))[0];

            switch (typeChar)
            {
            case 'b':  // Normal base type
                var baseType = new PostgresBaseType(ns, name, oid);
                Add(baseType);
                BaseTypes.Add(baseType);
                return;

            case 'a': // Array
            {
                var elementOID = Convert.ToUInt32(reader[reader.GetOrdinal("elemoid")]);
                Debug.Assert(elementOID > 0);
                if (!ByOID.TryGetValue(elementOID, out var elementPostgresType))
                {
                    Log.Trace($"Array type '{name}' refers to unknown element with OID {elementOID}, skipping", connector.Id);
                    return;
                }

                var arrayType = new PostgresArrayType(ns, name, oid, elementPostgresType);
                Add(arrayType);
                ArrayTypes.Add(arrayType);
                return;
            }

            case 'r': // Range
            {
                var elementOID = Convert.ToUInt32(reader[reader.GetOrdinal("elemoid")]);
                Debug.Assert(elementOID > 0);
                if (!ByOID.TryGetValue(elementOID, out var subtypePostgresType))
                {
                    Log.Trace($"Range type '{name}' refers to unknown subtype with OID {elementOID}, skipping", connector.Id);
                    return;
                }

                var rangeType = new PostgresRangeType(ns, name, oid, subtypePostgresType);
                Add(rangeType);
                RangeTypes.Add(rangeType);
                return;
            }

            case 'e':   // Enum
                var enumType = new PostgresEnumType(ns, name, oid);
                Add(enumType);
                EnumTypes.Add(enumType);
                return;

            case 'c':   // Composite
                var compositeType = new PostgresCompositeType(ns, name, oid);
                Add(compositeType);
                CompositeTypes.Add(compositeType);
                return;

            case 'd':   // Domain
                var baseTypeOID = Convert.ToUInt32(reader[reader.GetOrdinal("typbasetype")]);
                Debug.Assert(baseTypeOID > 0);
                if (!ByOID.TryGetValue(baseTypeOID, out var basePostgresType))
                {
                    Log.Trace($"Domain type '{name}' refers to unknown base type with OID {baseTypeOID}, skipping", connector.Id);
                    return;
                }
                var domainType = new PostgresDomainType(ns, name, oid, basePostgresType);
                Add(domainType);
                DomainTypes.Add(domainType);
                return;

            case 'p':   // pseudo-type (record, void)
                // Hack this as a base type
                goto case 'b';

            default:
                throw new ArgumentOutOfRangeException($"Unknown typtype for type '{name}' in pg_type: {typeChar}");
            }
        }