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}"); } }