Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NpgsqlDataReader exception in ExecuteScalar is hidden by exception in Dispose #2621

Open
tedypranolo opened this issue Sep 15, 2019 · 0 comments

Comments

@tedypranolo
Copy link

commented Sep 15, 2019

In both 4.1.0-preview2 and 5.0.0.0 in unstable build. This is currently happening with ExecuteScalar. If the reader fails during Read (in this case an enum without a proper handler), it would throw an NpgsqlSafeReadException, which in turn would trigger Dispose. And within Dispose since it needs to continue Consume, it will throw another exception and hiding the original NpgsqlSafeReadException with the useful information.

Message: 
    Npgsql.NpgsqlException : Unknown message code: 0
  Stack Trace: 
    PGUtil.ValidateBackendMessageCode(BackendMessageCode code) line 65
    <<DoReadMessage>g__ReadMessageLong|0>d.MoveNext() line 882
    --- End of stack trace from previous location where exception was thrown ---
    NpgsqlDataReader.NextResult(Boolean async, Boolean isConsuming) line 353
    NpgsqlDataReader.Consume(Boolean async) line 749
    NpgsqlDataReader.Close(Boolean connectionClosing, Boolean async) line 820
    NpgsqlDataReader.Close() line 774
    NpgsqlDataReader.Dispose(Boolean disposing) line 757
    DbDataReader.Dispose()
    NpgsqlCommand.ExecuteScalar(Boolean async, CancellationToken cancellationToken) line 1021
    NpgsqlCommand.ExecuteScalar() line 995
    CompositeTests.CompositePostgresType() line 68

Here's the test code to generate this case

        public enum TestEnum
        {
            One,
            Two
        }
        class SomeComposite
        {
            /// <summary>
            /// An enum without proper handler
            /// </summary>
            public TestEnum Test { get; set; }
            public int X { get; set; }
            public string SomeText { get; set; } = "";
        }
        [Test]
        public void CompositePostgresType()
        {
            var csb = new NpgsqlConnectionStringBuilder(ConnectionString + ";Load Table Composites=true")
            {
                ApplicationName = nameof(PostgresType),
                Pooling = false
            };
            using (var conn = OpenConnection(csb))
            {
                conn.ExecuteNonQuery("CREATE TYPE pg_temp.comp1 as (x int, some_text text, test int)");
                conn.ReloadTypes();
                conn.TypeMapper.MapComposite<SomeComposite>("comp1");

                conn.ExecuteNonQuery(@"
                    CREATE FUNCTION pg_temp.func(id int,out comp1 comp1, OUT comp2 COMP1[])
                        LANGUAGE plpgsql AS
                    $$
                    BEGIN
                        comp1 = ROW(9, 'bar',1)::comp1;
                        comp2 = ARRAY[ROW(9, 'bar',1)::comp1];
                    END;
                    $$;
                    ");

                using (var cmd = new NpgsqlCommand("SELECT pg_temp.func(0)", conn))
                {
                    //this should throw NpgsqlSafeReadException but it will be overriden by an exception in Dispose
                    var value = cmd.ExecuteScalar();
                }
            }
        }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.