Npgsql: SQL query parsing bug (PG non-conforming strings mode)

Created on 30 Sep 2019  路  3Comments  路  Source: npgsql/npgsql

Steps to reproduce

void Main()
{
    string connectionString = "Host=dbtest;Port=5434;Database=5gukq3xew3b36gh3co6th1w;Username=postgres;Password=******;";
    using (NpgsqlConnection connection = new NpgsqlConnection(connectionString))
    {
        connection.Open();
        string sql = @"
select table_name
from information_schema.views
where table_name like @p0 escape '\' and
(is_updatable = 'NO') = @p1
";
        using (NpgsqlCommand command = new NpgsqlCommand(sql, connection))
        {
            command.Parameters.AddWithValue("@p0", "%trig%");
            command.Parameters.AddWithValue("@p1", true);
            using (NpgsqlDataReader reader = command.ExecuteReader())
            {
                reader.Read();
                reader[0].Dump();
            }
        }
    }
}

The issue

Exact same code returns successfully in v4.0.10

Exception message:
42703: column "p1" does not exist

Stack trace:

Code | 42703
-- | --
ColumnName | null
ConstraintName | null
Data | Data
DataTypeName | null
Detail | null
ErrorCode | -2147467259
File | parse_relation.c
HelpLink | null
Hint | null
HResult | -2147467259
InnerException | null
InternalPosition | 0
InternalQuery | null
InvariantSeverity | ERROR
IsTransient | False
Line | 3183
Message | 42703: column "p1" does not exist
MessageText | column "p1" does not exist
Position | 119
Routine | errorMissingColumn
SchemaName | null
Severity | ERROR
Source | Npgsql
SqlState | 42703
StackTrace | at Npgsql.NpgsqlConnector.<>c__DisplayClass159_0.<<DoReadMessage>g__ReadMessageLong\|0>d.MoveNext()--- End of stack trace from previous location where exception was thrown ---   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()   at Npgsql.NpgsqlConnector.<>c__DisplayClass159_0.<<DoReadMessage>g__ReadMessageLong\|0>d.MoveNext()--- End of stack trace from previous location where exception was thrown ---   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()   at Npgsql.NpgsqlDataReader.<NextResult>d__44.MoveNext()--- End of stack trace from previous location where exception was thrown ---   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)   at Npgsql.NpgsqlDataReader.NextResult()   at Npgsql.NpgsqlCommand.<ExecuteReaderAsync>d__101.MoveNext()--- End of stack trace from previous location where exception was thrown ---   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)   at Npgsql.NpgsqlCommand.ExecuteReader(CommandBehavior behavior)   at UserQuery.Main() in C:\Users\andreyb\AppData\Local\Temp\LINQPad5\_lyhfafmb\query_pkhfum.cs:line 46   at LINQPad.ExecutionModel.ClrQueryRunner.Run()   at LINQPad.ExecutionModel.Server.RunQuery(QueryRunner runner)   at LINQPad.ExecutionModel.Server.StartQuery(QueryRunner runner)   at LINQPad.ExecutionModel.Server.<>c__DisplayClass153_0.<ExecuteClrQuery>b__0()   at LINQPad.ExecutionModel.Server.SingleThreadExecuter.Work()   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)   at System.Threading.ThreadHelper.ThreadStart()
Statement | select table_namefrom information_schema.viewswhere table_name like $1 escape '\' and(is_updatable = 'NO') = @p1
TableName | null
TargetSite | TargetSite
Where | null

Further technical details

Npgsql version: 4.1.0
PostgreSQL version: 9.6.4
Operating system: Windows 10

Other details about my project setup:

bug

Most helpful comment

Reproduced.

I believe the statement from the exception gives us a hint of what's going on
select table_namefrom information_schema.viewswhere table_name like $1 escape '\' and(is_updatable = 'NO') = @p1

As you can see npgsql replaced @p0 with $1 but failed to do so for @p1.

@roji do you know by head if things changed around parameter substitution?

All 3 comments

Similar to #2656.

Reproduced.

I believe the statement from the exception gives us a hint of what's going on
select table_namefrom information_schema.viewswhere table_name like $1 escape '\' and(is_updatable = 'NO') = @p1

As you can see npgsql replaced @p0 with $1 but failed to do so for @p1.

@roji do you know by head if things changed around parameter substitution?

Nope, not to my knowledge. Will dive into it.

Was this page helpful?
0 / 5 - 0 ratings