Example #1
0
        internal TypeHandler this[NpgsqlDbType npgsqlDbType, Type specificType = null]
        {
            get
            {
                if (specificType != null && (npgsqlDbType & NpgsqlDbType.Enum) == 0 && (npgsqlDbType & NpgsqlDbType.Composite) == 0)
                {
                    throw new ArgumentException($"{nameof(specificType)} can only be used with {nameof(NpgsqlDbType.Enum)} or {nameof(NpgsqlDbType.Composite)}");
                }

                TypeHandler handler;
                if (ByNpgsqlDbType.TryGetValue(npgsqlDbType, out handler))
                {
                    return(handler);
                }

                if (specificType != null)  // Enum/composite
                {
                    // Note that enums and composites are never lazily activated - they're activated at the
                    // moment of mapping (or at connection time when globally-mapped)
                    if ((npgsqlDbType & NpgsqlDbType.Array) != 0)
                    {
                        // Already-activated array of enum/composite
                        if (ArrayHandlerByType != null && ArrayHandlerByType.TryGetValue(specificType, out handler))
                        {
                            return(handler);
                        }
                    }

                    // For non-array enum/composite, simply delegate to type inference
                    return(this[specificType]);
                }

                // Couldn't find already activated type, attempt to activate

                if (npgsqlDbType == NpgsqlDbType.Enum || npgsqlDbType == NpgsqlDbType.Composite)
                {
                    throw new InvalidCastException($"When specifying NpgsqlDbType.{nameof(NpgsqlDbType.Enum)}, {nameof(NpgsqlParameter.SpecificType)} must be specified as well");
                }

                // Base, range or array of base/range
                PostgresType postgresType;
                if (_postgresTypes.ByNpgsqlDbType.TryGetValue(npgsqlDbType, out postgresType))
                {
                    return(postgresType.Activate(this));
                }

                // We don't have a backend type for this NpgsqlDbType. This could be because it's not yet supported by
                // Npgsql, or that the type is missing in the database (old PG, missing extension...)
                TypeAndMapping typeAndMapping;
                if (!HandlerTypesByNpsgqlDbType.TryGetValue(npgsqlDbType, out typeAndMapping))
                {
                    throw new NotSupportedException("This NpgsqlDbType isn't supported in Npgsql yet: " + npgsqlDbType);
                }
                throw new NpgsqlException($"The PostgreSQL type '{typeAndMapping.Mapping.PgName}', mapped to NpgsqlDbType '{npgsqlDbType}' isn't present in your database. " +
                                          "You may need to install an extension or upgrade to a newer version.");
            }
        }
Example #2
0
#pragma warning disable CA1043
        internal TypeHandler this[Type type]
#pragma warning restore CA1043
        {
            get
            {
                if (ByType.TryGetValue(type, out var handler))
                {
                    return(handler);
                }

                // Try to find the backend type by a simple lookup on the given CLR type, this will handle base types.
                if (_postgresTypes.ByClrType.TryGetValue(type, out var postgresType))
                {
                    return(postgresType.Activate(this));
                }

                // Try to see if it is an array type
                var arrayElementType = GetArrayElementType(type);
                if (arrayElementType != null)
                {
                    if (ByType.TryGetValue(arrayElementType, out var elementHandler) &&
                        elementHandler.PostgresType.NpgsqlDbType.HasValue &&
                        ByNpgsqlDbType.TryGetValue(NpgsqlDbType.Array | elementHandler.PostgresType.NpgsqlDbType.Value, out handler))
                    {
                        return(handler);
                    }

                    // Enum and composite types go through the special _arrayHandlerByType
                    if (ArrayHandlerByType != null && ArrayHandlerByType.TryGetValue(arrayElementType, out handler))
                    {
                        return(handler);
                    }

                    // Unactivated array

                    // Special check for byte[] - bytea not array of int2
                    if (type == typeof(byte[]))
                    {
                        if (!_postgresTypes.ByClrType.TryGetValue(typeof(byte[]), out var byteaPostgresType))
                        {
                            throw new NpgsqlException("The PostgreSQL 'bytea' type is missing");
                        }
                        return(byteaPostgresType.Activate(this));
                    }

                    // Get the elements backend type and activate its array backend type
                    if (!_postgresTypes.ByClrType.TryGetValue(arrayElementType, out var elementPostgresType))
                    {
                        if (arrayElementType.GetTypeInfo().IsEnum)
                        {
                            throw new NotSupportedException($"The CLR enum type {arrayElementType.Name} must be mapped with Npgsql before usage, please refer to the documentation.");
                        }
                        throw new NotSupportedException($"The CLR type {arrayElementType} isn't supported by Npgsql or your PostgreSQL. " +
                                                        "If you wish to map it to a PostgreSQL composite type you need to register it before usage, please refer to the documentation.");
                    }

                    if (elementPostgresType == null)
                    {
                        throw new NotSupportedException($"The PostgreSQL {arrayElementType.Name} does not have an array type in the database");
                    }

                    return(elementPostgresType.Array.Activate(this));
                }

                // Range type which hasn't yet been set up
                if (type.GetTypeInfo().IsGenericType&& type.GetGenericTypeDefinition() == typeof(NpgsqlRange <>))
                {
                    if (!_postgresTypes.ByClrType.TryGetValue(type.GetGenericArguments()[0], out var subtypePostgresType) ||
                        subtypePostgresType.Range == null)
                    {
                        throw new NpgsqlException($"The .NET range type {type.Name} isn't supported in your PostgreSQL, use CREATE TYPE AS RANGE");
                    }

                    return(subtypePostgresType.Range.Activate(this));
                }

                // Nothing worked
                if (type.GetTypeInfo().IsEnum)
                {
                    throw new NotSupportedException($"The CLR enum type {type.Name} must be registered with Npgsql before usage, please refer to the documentation.");
                }

                if (typeof(IEnumerable).IsAssignableFrom(type))
                {
                    throw new NotSupportedException("Npgsql 3.x removed support for writing a parameter with an IEnumerable value, use .ToList()/.ToArray() instead");
                }

                throw new NotSupportedException($"The CLR type {type} isn't supported by Npgsql or your PostgreSQL. " +
                                                "If you wish to map it to a PostgreSQL composite type you need to register it before usage, please refer to the documentation.");
            }
        }