-
Notifications
You must be signed in to change notification settings - Fork 124
Description
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;
endNow, 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