-
Notifications
You must be signed in to change notification settings - Fork 874
Milestone
Description
Steps to reproduce
We are trying to migrate from Npgsql 6.0.13 to 8.0.6 and have a problem with composite type mapping for postgresql types with dots in names
- Create postgresql type and functions
Postgresql code
drop function if exists "testproc";
drop type if exists public."test.mytype" cascade;
create type public."test.mytype" as
(
-- ids
guid uuid,
int64 bigint
);
drop function if exists "testproc";
CREATE OR REPLACE FUNCTION "testproc"(id public."test.mytype")
RETURNS table(guid uuid, int64 bigint)
AS
$$
BEGIN
return query (select id.guid, id.int64);
END
$$
LANGUAGE plpgsql;
drop function if exists "testprocarr";
CREATE OR REPLACE FUNCTION "testprocarr"(ids public."test.mytype"[])
RETURNS table(guid uuid, int64 bigint)
AS
$$
BEGIN
return query (select * from unnest(ids));
END
$$
LANGUAGE plpgsql;
select * from testproc(('9529d7c1-9303-46ee-92a5-0bb183de06d2', 456456)::public."test.mytype");
select * from testprocarr(array[('9529d7c1-9303-46ee-92a5-0bb183de06d3', 123123)::public."test.mytype"]);
- Execute DoTest()
C# code
using System.Data;
using Npgsql;
using NpgsqlTypes;
namespace ConsoleApp1;
static public class Test
{
public class NpgsqlGuidInt64Type
{
[PgName("guid")]
public Guid Id;
[PgName("int64")]
public Int64 Int64;
}
public static void DoTest()
{
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
AppContext.SetSwitch("Npgsql.EnableStoredProcedureCompatMode", true);
NpgsqlConnection.GlobalTypeMapper.MapComposite<NpgsqlGuidInt64Type>("public.test.mytype");
var connectionStringBuilder = new NpgsqlConnectionStringBuilder()
{
Host = "localhost",
Database = "mydatabase",
Username = "postgres",
Password = "postgres",
IncludeErrorDetail = true
};
using var connection = new NpgsqlConnection(connectionStringBuilder.ToString());
connection.Open();
try
{
Console.WriteLine("Testing call with composite type: public.test.mytype");
DoTestInternal(connection);
}
catch (Exception e)
{
Console.WriteLine(e);
}
try
{
Console.WriteLine("Testing call with array of composite types: public.test.mytype[]");
DoTestArray(connection);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
private static void DoTestInternal(NpgsqlConnection connection)
{
using var command = connection.CreateCommand();
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "testproc";
var parameter = new NpgsqlGuidInt64Type()
{
Id = Guid.NewGuid(),
Int64 = Int64.MaxValue
};
var npgsqlParameter = new NpgsqlParameter
{
ParameterName = "id",
Value = parameter,
DataTypeName = $"public.test.mytype"
};
command.Parameters.Add(npgsqlParameter);
using var reader = command.ExecuteReader();
while(reader.Read())
Console.WriteLine(reader["guid"]);
}
private static void DoTestArray(NpgsqlConnection connection)
{
using var command = connection.CreateCommand();
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "testprocarr";
var parameters = new List<NpgsqlGuidInt64Type>();
parameters.Add(new NpgsqlGuidInt64Type()
{
Id = Guid.NewGuid(),
Int64 = Int64.MaxValue
});
parameters.Add(new NpgsqlGuidInt64Type()
{
Id = Guid.NewGuid(),
Int64 = Int64.MinValue
});
var parameter = new NpgsqlParameter<IList<NpgsqlGuidInt64Type>>
{
ParameterName = "ids",
Value = parameters,
DataTypeName = $"public.test.mytype[]"
};
command.Parameters.Add(parameter);
using var reader = command.ExecuteReader();
while(reader.Read())
Console.WriteLine(reader["guid"]);
}
}output
Testing call with composite type: public.test.mytype
System.NotSupportedException: The data type name 'public.test.mytype' isn't present in your database. You may need to install an extension or upgrade to a newer version.
at Npgsql.NpgsqlParameter.<ResolveTypeInfo>g__ThrowNotSupported|111_1(String dataTypeName)
at Npgsql.NpgsqlParameter.ResolveTypeInfo(PgSerializerOptions options)
at Npgsql.NpgsqlParameterCollection.ProcessParameters(PgSerializerOptions options, Boolean validateValues, CommandType commandType)
at Npgsql.NpgsqlCommand.ExecuteReader(Boolean async, CommandBehavior behavior, CancellationToken cancellationToken)
at Npgsql.NpgsqlCommand.ExecuteReader(Boolean async, CommandBehavior behavior, CancellationToken cancellationToken)
at Npgsql.NpgsqlCommand.ExecuteReader(CommandBehavior behavior)
at ConsoleApp1.Test.DoTestInternal(NpgsqlConnection connection) in C:\Users\dvasilyev\RiderProjects\ConsoleApp1\ConsoleApp1\Test.cs:line 82
at ConsoleApp1.Test.DoTest() in C:\Users\dvasilyev\RiderProjects\ConsoleApp1\ConsoleApp1\Test.cs:line 41
Testing call with array of composite types: public.test.mytype[]
System.NotSupportedException: The data type name 'public._test.mytype' isn't present in your database. You may need to install an extension or upgrade to a newer version.
at Npgsql.NpgsqlParameter.<ResolveTypeInfo>g__ThrowNotSupported|111_1(String dataTypeName)
at Npgsql.NpgsqlParameter.ResolveTypeInfo(PgSerializerOptions options)
at Npgsql.NpgsqlParameterCollection.ProcessParameters(PgSerializerOptions options, Boolean validateValues, CommandType commandType)
at Npgsql.NpgsqlCommand.ExecuteReader(Boolean async, CommandBehavior behavior, CancellationToken cancellationToken)
at Npgsql.NpgsqlCommand.ExecuteReader(Boolean async, CommandBehavior behavior, CancellationToken cancellationToken)
at Npgsql.NpgsqlCommand.ExecuteReader(CommandBehavior behavior)
at ConsoleApp1.Test.DoTestArray(NpgsqlConnection connection) in C:\Users\dvasilyev\RiderProjects\ConsoleApp1\ConsoleApp1\Test.cs:line 115
at ConsoleApp1.Test.DoTest() in C:\Users\dvasilyev\RiderProjects\ConsoleApp1\ConsoleApp1\Test.cs:line 51
The issue
After connection npgsql parse this type as namespace = "test", and typename = "mytype".
But postgresql returns namespace = public, typename = "test.mytype"
Further technical details
Npgsql version: 8.0.6
PostgreSQL version: 16.4
Operating system: Rocky 9.4
###PR #5971
Reactions are currently unavailable