Skip to content

Problem with interplay between simple and extended prepared statements when using prepared_statement = 'full' #604

@mijoharas

Description

@mijoharas

Hey!

So, I managed to create a reliable repro of an issue I was having with prepared statements.

I've reproduced the issue on both main and 0.1.13 (which was the version we were using so the first we tested).

Start pgdog with prepared_statements = 'full' (basically just defaults other than that, other than hooking up a test db):

RUST_LOG=trace ./target/debug/pgdog -c ./local.pgdog.toml -u ./local.users.toml

Open another psql separately to your test db, and prepare a query (you should be able to execute it):

(michael)@127.0.0.1:6432 12:39:25 [cleo_development]
# prepare testplanmike1(int) as select 1 from users where id = $1;
PREPARE
(michael)@127.0.0.1:6432 12:39:29 [cleo_development]
# execute testplanmike1(1);
 ?column?
----------
        1
(1 row)

Then open something else that uses the extended query protocol, and run some prepared statements (I use rails, simplest way I had to do that was something like:

ApplicationRecord.descendants.take(30).each do |bar|
  bar.where(id: 1).to_a;
end

Now, for me, (seemingly reliably) I get an error executing the extended protocol query:

ActiveRecord::StatementInvalid: PG::InvalidSqlStatementName: ERROR:  prepared statement "a5" does not exist (ActiveRecord::StatementInvalid)
from /home/michael/.local/share/mise/installs/ruby/3.4.5/lib/ruby/gems/3.4.0/bundler/gems/rails-014cfe9c63a6/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb:917:in 'PG::Connection#exec_prepared'
Caused by PG::InvalidSqlStatementName: ERROR:  prepared statement "a5" does not exist

from /home/michael/.local/share/mise/installs/ruby/3.4.5/lib/ruby/gems/3.4.0/bundler/gems/rails-014cfe9c63a6/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb:917:in 'PG::Connection#exec_prepared'

And, going back to the original psql the prepared statement we created no longer works:

(michael)@127.0.0.1:6432 12:39:31 [cleo_development]
# execute testplanmike1(1);
ERROR:  prepared statement "__pgdog_1" does not exist

I don't see any of the extended protocol prepared statements when I look in show prepared; in the admin db.
Here is the relevant part of the trace:

2025-11-12T12:45:52.803376Z DEBUG pgdog::backend::pool::guard: [cleanup] no cleanup needed, server in "idle" state [127.0.0.1:5432, cleo_development]
2025-11-12T12:46:11.197607Z TRACE pgdog::frontend::client: request buffered [0.0501ms]
ClientRequest {
    messages: [
        Query(
            Query {
                query: "execute testplanmike1(1);",
            },
        ),
    ],
    route: Some(
        Route {
            shard: All,
            read: false,
            order_by: [],
            aggregate: Aggregate {
                targets: [],
                group_by: [],
            },
            limit: Limit {
                limit: None,
                offset: None,
            },
            lock_session: false,
            distinct: None,
            maintenance: false,
            rewrite_plan: RewritePlan {
                drop_columns: [],
                helpers: [],
            },
            rewritten_sql: None,
            explain: None,
            rollback_savepoint: false,
        },
    ),
}
2025-11-12T12:46:11.197976Z DEBUG pgdog::frontend::router::parser::query: parser is enabled
2025-11-12T12:46:11.198463Z DEBUG pgdog::frontend::router::parser::query: execute testplanmike1(1);
2025-11-12T12:46:11.198480Z TRACE pgdog::frontend::router::parser::query: CachedAst {
    cached: false,
    comment_shard: All,
    comment_role: None,
    inner: CachedAstInner {
        ast: ParseResult {
            protobuf: ParseResult {
                version: 170004,
                stmts: [
                    RawStmt {
                        stmt: Some(
                            Node {
                                node: Some(
                                    ExecuteStmt(
                                        ExecuteStmt {
                                            name: "testplanmike1",
                                            params: [
                                                Node {
                                                    node: Some(
                                                        AConst(
                                                            AConst {
                                                                isnull: false,
                                                                location: 22,
                                                                val: Some(
                                                                    Ival(
                                                                        Integer {
                                                                            ival: 1,
                                                                        },
                                                                    ),
                                                                ),
                                                            },
                                                        ),
                                                    ),
                                                },
                                            ],
                                        },
                                    ),
                                ),
                            },
                        ),
                        stmt_location: 0,
                        stmt_len: 24,
                    },
                ],
            },
            warnings: [],
            tables: [],
            aliases: {},
            cte_names: [],
            functions: [],
            filter_columns: [],
        },
        stats: Mutex {
            data: Stats {
                hits: 1,
                misses: 0,
                direct: 0,
                multi: 0,
            },
        },
    },
}
2025-11-12T12:46:11.198802Z DEBUG pgdog::frontend::router::parser::query: rewrite needed
2025-11-12T12:46:11.198969Z TRACE pgdog::frontend::client::query_engine::route_query: routing [
    Query(
        Query {
            query: "execute testplanmike1(1);",
        },
    ),
] to Rewrite(
    "EXECUTE __pgdog_1(1)",
)
2025-11-12T12:46:11.199132Z DEBUG pgdog::backend::pool::connection::binding: server is in "idle" state [127.0.0.1:5432, cleo_development]
2025-11-12T12:46:11.199191Z DEBUG pgdog::frontend::client::query_engine::connect: client paired with [127.0.0.1:5432, cleo_development] using route [shard=all, role=primary] [0.0995ms]
2025-11-12T12:46:11.199407Z DEBUG pgdog::backend::server: syncing 10 params
2025-11-12T12:46:11.199426Z DEBUG pgdog::backend::server: RESET "application_name" [127.0.0.1:5432, cleo_development]
2025-11-12T12:46:11.199439Z DEBUG pgdog::backend::server: RESET "client_min_messages" [127.0.0.1:5432, cleo_development]
2025-11-12T12:46:11.199449Z DEBUG pgdog::backend::server: RESET "idle_in_transaction_session_timeout" [127.0.0.1:5432, cleo_development]
2025-11-12T12:46:11.199459Z DEBUG pgdog::backend::server: RESET "intervalstyle" [127.0.0.1:5432, cleo_development]
2025-11-12T12:46:11.199469Z DEBUG pgdog::backend::server: RESET "lock_timeout" [127.0.0.1:5432, cleo_development]
2025-11-12T12:46:11.199479Z DEBUG pgdog::backend::server: RESET "search_path" [127.0.0.1:5432, cleo_development]
2025-11-12T12:46:11.199490Z DEBUG pgdog::backend::server: RESET "standard_conforming_strings" [127.0.0.1:5432, cleo_development]
2025-11-12T12:46:11.199501Z DEBUG pgdog::backend::server: RESET "statement_timeout" [127.0.0.1:5432, cleo_development]
2025-11-12T12:46:11.199512Z DEBUG pgdog::backend::server: RESET "timezone" [127.0.0.1:5432, cleo_development]
2025-11-12T12:46:11.199522Z DEBUG pgdog::backend::server: SET "application_name" TO 'psql' [127.0.0.1:5432, cleo_development]
2025-11-12T12:46:11.199582Z TRACE pgdog::net::stream: [127.0.0.1:5432] <-- Query(
    Query {
        query: "RESET \"application_name\"",
    },
)
2025-11-12T12:46:11.199614Z TRACE pgdog::net::stream: [127.0.0.1:5432] <-- Query(
    Query {
        query: "RESET \"client_min_messages\"",
    },
)
2025-11-12T12:46:11.199631Z TRACE pgdog::net::stream: [127.0.0.1:5432] <-- Query(
    Query {
        query: "RESET \"idle_in_transaction_session_timeout\"",
    },
)
2025-11-12T12:46:11.199648Z TRACE pgdog::net::stream: [127.0.0.1:5432] <-- Query(
    Query {
        query: "RESET \"intervalstyle\"",
    },
)
2025-11-12T12:46:11.199665Z TRACE pgdog::net::stream: [127.0.0.1:5432] <-- Query(
    Query {
        query: "RESET \"lock_timeout\"",
    },
)
2025-11-12T12:46:11.199681Z TRACE pgdog::net::stream: [127.0.0.1:5432] <-- Query(
    Query {
        query: "RESET \"search_path\"",
    },
)
2025-11-12T12:46:11.199697Z TRACE pgdog::net::stream: [127.0.0.1:5432] <-- Query(
    Query {
        query: "RESET \"standard_conforming_strings\"",
    },
)
2025-11-12T12:46:11.199714Z TRACE pgdog::net::stream: [127.0.0.1:5432] <-- Query(
    Query {
        query: "RESET \"statement_timeout\"",
    },
)
2025-11-12T12:46:11.199730Z TRACE pgdog::net::stream: [127.0.0.1:5432] <-- Query(
    Query {
        query: "RESET \"timezone\"",
    },
)
2025-11-12T12:46:11.199747Z TRACE pgdog::net::stream: [127.0.0.1:5432] <-- Query(
    Query {
        query: "SET \"application_name\" TO 'psql'",
    },
)
2025-11-12T12:46:11.200460Z DEBUG pgdog::frontend::client::query_engine::query: cross-shard queries disabled: false
2025-11-12T12:46:11.200550Z TRACE pgdog::net::stream: [127.0.0.1:5432] <-- Query(
    Query {
        query: "EXECUTE __pgdog_1(1)",
    },
)
2025-11-12T12:46:11.200905Z TRACE pgdog::net::stream: [127.0.0.1:56190] <-- ErrorResponse {
    severity: "ERROR",
    code: "26000",
    message: "prepared statement \"__pgdog_1\" does not exist",
    detail: None,
    context: None,
    file: Some(
        "prepare.c",
    ),
    routine: Some(
        "FetchPreparedStatement",
    ),
}
2025-11-12T12:46:11.200993Z ERROR pgdog::net::stream: [127.0.0.1:56190] <-- ERROR: 26000 prepared statement "__pgdog_1" does not exist

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions